python3学习笔记之列表和元组
文章目录
- 列表元组基础
- 列表和元组的存储差异
- 列表元组性能差异
- 列表元组使用场景
- 总结
- 思考题
列表元组基础
列表和元组,都是一个可以放置任意数据类型的有序集合
- 列表是动态的,长度大小不固定,可以随意地增加、删减或者改变元素(mutable)。而元组是静态的,长度大小固定,无法增加删减或者改变(immutable)。
- Python 中的列表和元组都支持负数索引,-1 表示最后一个元素,-2 表示倒数第二个元素
列表和元组都支持切片操作
li = [2,4,6,8]
li[1:3]
[4,6]
tup = (1,3,5,7)
tup[0:2]
(1,3)
- 列表和元组都可以随意嵌套
列表元组可以通过list()和tuple()函数相互转换
tuple([2,4,6,8])
(2,4,6,8)
list((1,3,5,7))
[1,3,5,7]
列表和元组常用内置函数
count(item)表示统计列表 / 元组中 item 出现的次数
li = [2,4,6,8,2]
li.count(2)
2
index(item)表示返回列表 / 元组中 item 第一次出现的索引
li = [2,4,6,8,2]
li.index(2)
0
list.reverse()和list.sort()分别表示原地倒转列表和排序(ps:元组没有这两个内置函数)
li = [2,4,6,8,2]
li.reverse()
[2,8,6,4,2]
reversed() 和 sorted() 同样表示对列表 / 元组进行倒转和排序,reversed() 返回一个倒转后的迭代器,sorted() 返回排好序的新列表。此处对元组和列表的操作不是原地操作
tup = (1,3,5,7)
reversedTup = reversed(tup)
for item in reversedTup:
print(item,end = ' ' )
7 5 3 1
sortedTup = sorted(tup,reverse = True)#默认reverse为False,为False时按从小到大顺序排序
print(sortedTup)
(7,3,5,1)
列表和元组的存储差异
l = [1, 2, 3]
l.__sizeof__()
64
tup = (1, 2, 3)
tup.__sizeof__()
48
你可以看到,对列表和元组,我们放置了相同的元素,但是元组的存储空间,却比列表要少 16 字节。why???
由于列表是动态的,所以它需要存储指针,来指向对应的元素(上述例子中,对于 int 型,8 字节)。另外,由于列表可变,所以需要额外存储已经分配的长度大小(8 字节),这样才可以实时追踪列表空间的使用情况,当空间不足时,及时分配额外空间
l = []
l.__sizeof__() // 空列表的存储空间为40字节
40
l.append(1)
l.__sizeof__()
72 // 加入了元素1之后,列表为其分配了可以存储4个元素的空间 (72 - 40)/8 = 4
l.append(2)
l.__sizeof__()
72 // 由于之前分配了空间,所以加入元素2,列表空间不变
l.append(3)
l.__sizeof__()
72 // 同上
l.append(4)
l.__sizeof__()
72 // 同上
l.append(5)
l.__sizeof__()
104 // 加入元素5之后,列表的空间不足,所以又额外分配了可以存储4个元素的空间
上面的例子,大概描述了列表空间分配的过程。我们可以看到,为了减小每次增加 / 删减操作时空间分配的开销,Python 每次分配空间时都会额外多分配一些,这样的机制(over-allocating)保证了其操作的高效性:增加 / 删除的时间复杂度均为 O(1)。
**ps:**数据量较小时,列表和元组的在存储上的性能差异可以忽略不计,但对于海量数据(一亿甚至十亿数据)这种存储上的数据不能忽略
列表元组性能差异
元组要比列表更加轻量级一些,所以总体上来说,元组的性能速度要略优于列表
- 资源缓存:python会在后台会对一些静态数据做一些资源缓存(resource caching),对于元组这些静态变量若它不被使用且占用空间不大时,python的垃圾回收并不会立即回收这部分内存,下次若创建同样大小的元组时,可以直接利用之前缓存的内存资源,这样可以大大加快程序运行速度。而对于列表这种非静态数据若这些变量不被使用会被python的垃圾回收机制立马回收。
元组初始化速度快于列表,如下可以看出元组出事化速度要比列表块5倍
python3 -m timeit 'x=(1,2,3,4,5,6)'
20000000 loops, best of 5: 9.97 nsec per loop
python3 -m timeit 'x=[1,2,3,4,5,6]'
5000000 loops, best of 5: 50.1 nsec per loop
- 索引操作元组和列表速度差别可忽略不计
- 对元素的增加删除或改变,列表显然由于列表(元组必须通过新建一个元组来完成)
列表元组使用场景
- 如果存储的数据和数量不变,比如你有一个函数,需要返回的是一个地点的经纬度,然后直接传给前端渲染,那么肯定选用元组更合适。
- 如果存储的数据或数量是可变的,比如社交平台上的一个日志功能,是统计一个用户在一周之内看了哪些用户的帖子,那么则用列表更合适。
总结
列表和元组都是有序的,可以存储任意数据类型的集合,区别主要在于下面这两点。
- 列表是动态的,长度可变,可以随意的增加、删减或改变元素。列表的存储空间略大于元组,性能略逊于元组。
- 元组是静态的,长度大小固定,不可以对元素进行增加、删减或者改变操作。
- 元组相对于列表更加轻量级,性能稍优。
思考题
# 创建空列表
# option A
empty_list = list()
# option B
empty_list = []
A、B 两种方式,请问它们在效率上有什么区别吗?我们应该优先考虑使用哪种呢?
answer:A、B 两种方式区别主要在于list()是一个function call,Python的function call会创建stack,并且进行一系列参数检查的操作,比较expensive,反观[]是一个内置的C函数,可以直接被调用,因此效率高。
还没有评论,来说两句吧...