Python中最常见的两种数据结构:列表(list)和元组(tuple),它们都是可以存放任意数据类型的有序集合。
ls = [1, 2, 'hello', 'world'] # 列表中同时含有 int 和 string 类型的元素 tup = ('jason', 22) # 元组中同时含有 int 和 string 类型的元素
list与tuple的区别:
一、列表是动态的,长度大小不固定,可以随意的增、删、改元素;元组是静态的,长度大小固定,不可随意增、删、改元素。
ls = ['1', '2', '3', '4'] ls.append('5') ls[2] = '6' print ls ['1', '2', '6', '4', '5']
tp = ('1', '2', '3', '4') tp[2] = 6 报错: TypeError: 'tuple' object does not support item assignment
要想改变元组,只能重新开辟一块内存,创建新的元组。原来的元组还是没有改变
new_tuple = tp + ('5',) print tp, new_tuple ('1', '2', '3', '4') ('1', '2', '3', '4', '5')
二、存储方式的差异
tup = (3, 2, 3, 7) ls = [3, 2, 3, 7] print tup.__sizeof__(), ls.__sizeof__() 56 72
可以看出,对列表和元组,我们放置了相同的元素,但是元组的存储空间,却比列表要少 16 字节。
原因:由于列表是动态的,所以它需要存储指针,来指向对应的元素(上述例子中,对于 int 型,8 字节)。另外,由于列表可变,所以需要额外存储已经分配的长度大小(8 字 节),这样才可以实时追踪列表空间的使用情况,当空间不足时,及时分配额外空间。
l = [] print l.__sizeof__() 40 // 空列表的存储空间为 40 字节 l.append(1) print l.__sizeof__() 72 // 加入了元素 1 之后,列表为其分配了可以存储 4 个元素的空间 (72 - 40)/8 = 4 l.append(2) l.append(3) l.append(4) print l.__sizeof__() 72 // 同上 l.append(5) print l.__sizeof__() 104 // 加入元素 5 之后,列表的空间不足,所以又额外分配了可以存储 4 个元素的空间
所以,。我们可以看到,为了减小每次增加 / 删减 操作时空间分配的开销,Python 每次分配空间时都会额外多分配一些,这样的机制 (over-allocating)保证了其操作的高效性:增加 / 删除的时间复杂度均为 O(1)。但是对于元组,情况就不同了。元组长度大小固定,元素不可变,所以存储空间固定。
从列表和元组的存储方式上,我们可以学习到,元组要比列表更加轻量级一些, 所以总体上来说,元组的性能速度要略优于列表。
list和tuple常用的函数:
相互转换:
list((1, 2, 3)) [1, 2, 3] tuple([1, 2, 3]) (1, 2, 3)
常用的内置函数:
ls = ['6', '7', '8', '9', '8', '5', '3'] print ls.count('8') 2 print ls.index('5') 5 ls.reverse() print ls ['3', '5', '8', '9', '8', '7', '6'] ls.sort() print ls ['3', '5', '6', '7', '8', '8', '9'] print reversed(ls) <listreverseiterator object at 0x101f00f50> print list(reversed(ls)) ['6', '7', '8', '9', '8', '5', '3'] tup = (3, 2, 3, 7, 8, 1) print tup.count(3) 2 print tup.index(8) 4 print reversed(tup) <reversed object at 0x109680f50> print tuple(reversed(tup)) (1, 8, 7, 3, 2, 3) print list(reversed(tup)) [1, 8, 7, 3, 2, 3] print sorted(tup) [1, 2, 3, 3, 7, 8]
count(item) 表示统计列表 / 元组中 item 出现的次数。
index(item) 表示返回列表 / 元组中 item 第一次出现的索引。
list.reverse() 和 list.sort() 分别表示原地倒转列表和排序(注意,元组没有内置的这两个 函数)。
reversed() 表示对列表 / 元组进行倒转,但是会返回一个倒转后对象,再通过list或tuple来转换。
sorted()sorted() 表示对列表 / 元组进行排序,但是会返回一个排好序的新的列表。
总结:
列表是动态的,长度可变,可以随意的增加、删减或改变元素。列表的存储空间略大于元 组,性能略逊于元组。
元组是静态的,长度大小固定,不可以对元素进行增加、删减或者改变操作。元组相对于 列表更加轻量级,性能稍优