码迷,mamicode.com
首页 > 编程语言 > 详细

Python 核心技术与实战 --01 列表与元祖

时间:2019-12-21 15:43:41      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:引用计数   art   hash   sub   net   init   iad   pointer   size_t   

2019-12-21

本文章主要讲述Python的列表元组

高级内容:

列表与元组存储方式的差异

了解 dir() 函数的概念:

   dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。

l = [1,3,3,4,8]
print(dir(l))


[__add__, __class__, __contains__,  \

__delattr__, __delitem__, __dir__, \

__doc__, __eq__, __format__, __ge__, \

__getattribute__, __getitem__, __gt__, \

__hash__, __iadd__, __imul__, __init__,\

__init_subclass__, __iter__, __le__, \

__len__, __lt__, __mul__, __ne__, \

__new__, __reduce__, __reduce_ex__, \

__repr__, __reversed__, __rmul__, \

__setattr__, __setitem__, __sizeof__, \

__str__, __subclasshook__, append, clear, \

copy, count, extend, index, insert, pop, remove, reverse, sort]
#list 的详细内容

l = [1,2,3]
print(l.__sizeof__())


64

tup =(1,2,3)
print(tup.__sizeof__())

 

48

列表和元组内的元素相同,但是 元组比列表少了 16 个字节, 为什么呢?

 

由于列表是动态的,所以它需要存储指针,来指向对应的元素(上述例子中,对于int类型,8个字节)。另外由于列表可变,所以需要额外存储已经分配的长度大小(8字节),这样才能实时追踪列表空间的使用情况,当空间不足时,及时分配额外空间。

可以看一下 python list  C 源码:

      https://blog.csdn.net/qq_33339479/article/details/81807096

#define PyObject_VAR_HEAD      PyVarObject ob_base;
#define Py_INVALID_SIZE (Py_ssize_t)-1

/* Nothing is actually declared to be a PyObject, but every pointer to
 * a Python object can be cast to a PyObject*.  This is inheritance built
 * by hand.  Similarly every pointer to a variable-size Python object can,
 * in addition, be cast to PyVarObject*.
 */
typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;                                       // 引用计数值
    struct _typeobject *ob_type;                                // 基本的类型 type
} PyObject;

typedef struct {
    PyObject ob_base;                                           // 对象基本信息
    Py_ssize_t ob_size; /* Number of items in variable part */  // 变长对象的元素个数
} PyVarObject;
...
typedef struct {
    PyObject_VAR_HEAD                                           // 变量头部信息
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;                                         // 元素指向具体指

    /* ob_item contains space for allocated elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size
     *     ob_item == NULL implies ob_size == allocated == 0
     * list.sort() temporarily sets allocated to -1 to detect mutations.
     *
     * Items must normally not be NULL, except during construction when
     * the list is not yet visible outside the function that builds it.
     */
    Py_ssize_t allocated;                                       // 当前空间
} PyListObject;
l = []
print(l.__sizeof__())

l.append(1)
print(l.__sizeof__())

l.append(2)
print(l.__sizeof__())



40 
72
72

列表的空间分配的过程可以看到,为了减小每次增加/删除的开销,python每次分配空间的时候都会多分配一点,这样的机制保证了其操作的高效性:增加/删除的时间复杂度均为O(1)

因为元组是静态的所以Python对于小量的静态内存就会放到缓存里面,下次分配同样多的元组时,就不用向操作系统发出请求了,就直接分配之前的缓存的内存空间。这样程序的运行速度就得到保证

初始化过程 python 3.7.0  列表优于元组(少量数据的时候)

C:\Users\qf>python -m timeit x=(1,2,3,4,5,6)
20000000 loops, best of 5: 12.5 nsec per loop

C:\Users\qf>python -m timeit x=[1,2,3,4,5,6]‘(少量数据的时候)
20000000 loops, best of 5: 12.2 nsec per loop

 

python 3.7.0   索引操作 列表 优于元组了
:\Users\qf>python -m timeit -s x=[1,2,3,4,5,6]
0000000 loops, best of 5: 12.2 nsec per loop

:\Users\qf>python -m timeit -s x=(1,2,3,4,5,6)
0000000 loops, best of 5: 13.7 nsec per loop

列表和元组的使用场景

1. 如果存储的数据和数量不变,比如你有一个函数,需要返回的是一个地点的经纬度,然后直接传给前端渲染,那么肯定选用元组更合适。

2.如果存储的数据或数量是可变的,比如社交平台上的一个日志功能,是统计一个用户在一周之内看了哪些用户的帖子,那么则用列表更合适

以下为基础内容:

1. 列表与元组基础

         共同点: 列表和元组都是一个可以放置任意数据类型的有序集合。

         不同点:1. 列表 是动态的,长度大小不固定,可以随意增加/删除 改变元素(mutable)

                           元组是静态的,长度大小固定,无法增加删减或者改变(immutable)

例子1:

1 # 列表的例子
2 l = [1, 2, 3, 4]
3 l[0] = 2
4 print(l)
[2, 2, 3, 4]

1 # 元组的例子
2 tup = (1, 2, 3, 4)
3 tup[0] = 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-77cf1f9285bd> in <module>
      1 # 元组的例子
      2 tup = (1, 2, 3, 4)
----> 3 tup[0] = 2
      4 

TypeError: tuple object does not support item assignment

但是你想对已有的元组做修改该怎么办呢?

答案:开辟一块新的内存,创建新的元组

# 元组和列表增加的例子
tup = (1, 2, 3, 4)
new_tup = tup + (5,)
print(new_tup)

l = [1,2,3,4]
l.append(5)
print(l)

执行结果: (
1, 2, 3, 4, 5) [1, 2, 3, 4, 5]

2.列表和元组的索引

python 的列表和元组都支持负索引切片

列表和 元组支持任意嵌套

l = [[1,2,3],[4,5,6]]
tup =((1,2,3),(4,5,6))

通过 list() 和 tuple() 可以将两者相互转换.

3. 列表和元组常用的内置函数

(1) count()

# 元组和列表增加的例子
tup = (1, 2, 3, 4)
new_tup = tup + (5,)
print(new_tup.count(1))

l = [1,2,3,4]
l.append(5)
print(l.count(1))

执行结果
1
1

(2) index(item) 给出第一次出现的item 的索引

(3) list.reverse() 原地倒转列表 (元组没有)

l = [1,3,3,4,8]
l.append(5)
l.reverse()
print(l)



[5, 8, 4, 3, 3, 1]

 

(4) list.sort() 排序列表 (元组没有)

l = [1,3,3,4,8]
l.append(5)
l.reverse()
l.sort()
print(l)


[1, 3, 3, 4, 5, 8]

(5)reserved() 翻转后返回一个新的列表或元组

 

(6) sorted()排序后返回一个新的列表或元组

Python 核心技术与实战 --01 列表与元祖

标签:引用计数   art   hash   sub   net   init   iad   pointer   size_t   

原文地址:https://www.cnblogs.com/qifei-liu/p/12076976.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!