“ 几乎所有的编程语言都拥有集合类型,常见的集合类型有很多,例如:数组、栈、hash 等,而在 Python 中 List & Tuple 就是我们最常见的两种集合类型”
01
—
列表与元素的定义
从集合分类的角度来看列表与元组属于有序集合。而 Python 中的 List 与 Tuple 与大部分编程语言的序列略有不同的是:Python 的 List 与 Tuple 是异构的,也就是说集合中的元素可以是不同的数据类型:
- l = [1, "str", True] # define a list
复制代码- t = (1, 1.2, False) # define a tuple
复制代码 列表是动态的,元组是静态的
- print(l) # [1, "str", 10] will be print to the console.
复制代码- [/code][code]t = (1, "str", False)
复制代码- t[2] = 10 # TypeError: 'tuple' object does not support item assignment
复制代码 这里针对元组的是否可变有一点需要说明,元组只是不允许内部存储值类型的值不可变,如果存储的是引用类型,引用指向的值是可以改变的:
- print(t) # (1, 2, [3, 4]) will be printed.
复制代码- [/code][code]t[2][-1] = 'x'
复制代码- print(t) # (1, 2, [3, 'x']) will be printed.
复制代码
列表的存储空间要大于元组
- print(l.__sizeof__()) # 40
复制代码- print(t.__sizeof__()) # 24
复制代码 可以看到空列表占用 40 个字节,而空元组占用 24 个字节,这是因为 List 是动态的需要分配额外的存储空间记录已经分配的列表长度以便空间不足时进行及时的扩容。
元组的性能要高于列表
Python 与 Java、Go 一样都属于自动垃圾回收语言,所以语言本身会对不使用的变量进行内存的自动回收,但是有的时候为了提升语言的性能,语言自身不得不在一些特殊的场景进行缓存处理(Resource caching)。Python 语言对于一些占用空间不大的静态变量就会进行一些缓存处理,以便下次初始相同数据的时候提升性能。所以元组作为静态资源自然性能要优于列表,这里做一个语言级别的 benchmark 也可以很好的证明这点:
- $ python3 -m timeit 'l = [1, 2, 3]'
复制代码- # 5000000 loops, best of 5: 59.8 nsec per loop
复制代码- [/code][code]$ python3 -m timeit 't = (1, 2, 3)'
复制代码- # 20000000 loops, best of 5: 17.9 nsec per loop
复制代码- [/code][code]# 在 python3.7.4 版本下初始化的性能大约相差 4 倍
复制代码
02
—
列表与元组的操作
列表与元组的加法操作
- print(l) # [1, 2, 'a', 'b'] will be printed.
复制代码- print(t) # (1, 2, 'a', 'b') will be printed.
复制代码 列表与元组的乘法操作
- print(l) # [1, 2, 1, 2] will be printed.
复制代码- print(t) # (1, 2, 1, 2) will be printed.
复制代码 列表与元组的索引操作
- l = [1, 2, 3, 4, 5, 'b', 7, 8, 9]
复制代码- t = (1, 2, 3, 4, 5, 'a', 7, 8, 9)
复制代码- [/code][code]# 根据索引输出对应元素
复制代码- print(l[8]) # 9 will be printed.
复制代码- print(t[0]) # 1 will be printed.
复制代码- [/code][code]# 根据元素输出对应索引位置,如果元素不存在则抛出异常
复制代码- print(l.index('b')) # 5 will be printed.
复制代码- print(t.index('a')) # 5 will be printed.
复制代码
列表与元组的切片操作
- l = [1, 1, 'a', 'a', 'b', 'b', 'b']
复制代码- t = (1, 1, 'a', 'a', 'b', 'b', 'b')
复制代码- [/code][code]print(l[0:2]) # [1, 1] will be printed.
复制代码- print(t[0::2]) # (1, 'a', 'b', 'b') will be printed
复制代码 [start:end:step] 切片操作包含 start 位置的元素,不包含 end 位置的元素,每间隔 step 个元素取值,step 的值默认为 1,如果 start 或者 end 为缺省状态则包含 start 或者 end 的值。
列表的赋值操作
- l[2:4] = ['a', 'b', 'c', 'd']
复制代码- print(l) # [1, 2, 'a', 'b', 'c', 'd', 13]
复制代码 列表的删除操作
- print(l) # [2,3,4,5, 'a', 'a']
复制代码- [/code][code]# 元素 item 删除,如果存在多个相同元素,默认删除索引靠前的元素
复制代码- [/code][code]# 元素弹出式删除, 缺省参数时删除末尾元素
复制代码
列表的添加
- print(l) # [1,2,3,'a',['x', 'y']]
复制代码- print(l) # [1,True,2,3,'a',['x', 'y']]
复制代码 列表与元组的包含判断
- [/code][code]# 判断元素在列表中是否存在
复制代码- [/code][code]# 判断元素在列表中是否不存在
复制代码- print(10 not in t) # True
复制代码 列表与元组的元素个数统计
- l = [1, 1, 'a', 'a', 'b', 'b', 'b']
复制代码- t = (1, 1, 'a', 'a', 'b', 'b', 'b')
复制代码- [/code][code]# 获取列表与元组的总长度
复制代码- [/code][code]# 获取列表或元组中指定元素的个数
复制代码 列表与元组的排序
- print(l) # [1, 2, 3, 4, 5]
复制代码- [/code][code]# sorted 返回排序后的列表,原列表未被排序
复制代码- print(l) # [2, 1, 4, 5, 3]
复制代码- print(sl) # [1, 2, 3, 4, 5]
复制代码- [/code][code]t = (2, 1, 4, 5, 3)
复制代码- # sorted(tuple) 返回排序后的列表,原元组未被排序
复制代码- print(t) # (2, 1, 4, 5, 3)
复制代码- print(st) # [1, 2, 3, 4, 5],注意这里 st 的类型是一个列表
复制代码 列表与元组的反转
- [/code][code]# 原列表反转,返回值为 None
复制代码- [/code][code]# reversed(list) 原列表无变化,返回反转后的列表迭代对象
复制代码- [/code][code]# reversed(tuple) 原元组无变化,返回反转后的对象
复制代码
非常感谢您能读到这里,以上内容有哪些不足以及理解有误请留言指正或者到我的知识星球 Byte Hacking 中进行交流:
|
|