标签:引用计数 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. 列表 是动态的,长度大小不固定,可以随意增加/删除 改变元素(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]
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()排序后返回一个新的列表或元组
标签:引用计数 art hash sub net init iad pointer size_t
原文地址:https://www.cnblogs.com/qifei-liu/p/12076976.html