Python 核心技术与实战 --01 列表与元祖
Posted 小飞Python
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 核心技术与实战 --01 列表与元祖相关的知识,希望对你有一定的参考价值。
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 列表与元祖的主要内容,如果未能解决你的问题,请参考以下文章