Beaver's Blog

Freedom Openness Inclusion

0%

Python中的list和tuple

前言

tuplelist作为Python中的重要且频繁使用的基础数据类型,我们有必要进一步了解二者之间相同点和差异。

list和tuple基础知识

  • 什么是list和tuple?

    实际上,列表和元组都是一个可以放置任意数据类型的有序集合。

  • 二者的区别

    列表是动态的,长度大小不固定,可以随意地增加、删减或者改变元素。
    而元组是静态的,长度大小固定,无法增加删减或者改变。

如果tuple想要对元素进行增加、删改操作时,需要新创建一个tuple实现这些操作。而list只需使用append方法,将新的元素添加到列表中,而不会新建一个列表。

1
2
3
4
5
t = (11, 12, 13, 14)
l = [11, 12, 13, 14]
# adds an element to the tuple
t1 = t + (5,)
l.append(5)

tuple和list都支持负数索引、切片、嵌套等操作,而且tuple和list还可以通过list()及tuple()相互转换。

1
2
3
4
5
6
7
8
9
10
11
t=(1,2,3)
l=[1,2,3]
# 负数索引
t[-1] -->3
l[-2] -->2
# 切片
t[0,2] -->(1,2)
l[0,1] -->[1]
# 相互转换
l2=list(t)
t2=tuple(l)

list和tuple的常见内置方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# List
list = [] # create a new list

list[i] = val
list[i:j] = otherlist # replace ith to jth-1 elements with otherlist
del list[i:j]

list.append(item) # even the item is a list, but the list as a element in list
list.extend(another_list)
list.insert(index, item) #
list.pop() # returns and removes last element from the list
list.pop(i) # returns and removes i-th element from the list
list.remove(i) # removes the first item from the list whose value is i
list.copy() # returns a copy of the list
list1 + list2 # combine two list

list.reverse() # reverses the elements of the list in-place
list.count(item)

zip(list1, list2, ...) # returns list of tuples with n-th element of both list1
# and list2 and ...listn
list.sort() # sorts in-place, returns None
sorted(list) # returns sorted copy of list
",".join(list) # returns a string with list elements seperated by comma
# Tuple
tuple1 + tuple2 # return a new tuple contains tuple1 and tuple2
tuple.count() # Returns the number of times a specified value occurs in a tuple
tuple.index() # Searches the tuple for a specified value and returns the position of
# where it was found

二者的性能差异和使用场景

tuple和list的存储方式

上面说过,由于tuple和list特性不同,势必会影响二者的存储方式。

1
2
3
4
t = (1,2)
t.__sizeof__() -->40
l = [1,2]
l.__sizeof__() -->56

从上面我们可以看到,tuple和list存储了相同的元素下,list要比tuple多使用16字节的空间。

由于列表是动态的,所以它需要存储指针,来指向对应的元素(上述例子中,对于int 型,8 bytes)。另外,由于列表是可变的,所以需要额外存储已经分配的长度大小(8 bytes),这样才可以实时追踪列表空间的使用情况,当空间不足时,及时分配额外空间。

对于元组而言,由于元组长度大小固定,元素不可变,所以存储空间也是固定的。

当tuple和list存储的元素越来越多的时候,二者的差异的性能差异也将进一步体现。

性能差异

通过了解列表和元组存储方式的差异,我们可以得出结论:元组要比列表更加轻量级一些,所以总体上来说,元组的性能速度要略优于列表。

初始化相同元素的tuple和list,tuple速度更快。对于索引操作,二者没有明显差异。

如果想进行增加、删改操作时,list性能更好。因为这些操作,tuple都必须通过新建tuple实现。

使用场景

经过以上对比,该如何使用哪种类型?具体问题分析。

如果存储的数据和数量不变,应该选取tuple;如果存储的数据或数量是可变的,应选取list。

list和tuple的底层实现

list和tuple的内部实现都是array的形式,list因为可变,所以是一个over-allocate的array,tuple因为不可变,所以长度大小固定。

t=list(),t2=[]同样是新建一个列表,二者有什么区别?

主要在于list()是一个function调用,Python的函数调用会创建stack,并且进行一系列参数检查等操作,有一定的开销,而[]是一个内置的C函数,可以直接被调用,因此效率高。

总结

总的来说,列表和元组都是有序的,可以存储任意数据类型的集合,区别主要在于下面这两点:

列表是动态的,长度可变,可以随意的增加、删减或改变元素。列表的存储空间略大于元组,性能略逊于元组。
元组是静态的,长度大小固定,不可以对元素进行增加、删减或者改变操作。元组相对于列表更加轻量级,性能稍优。

通过本文的对listtuple的对比,想要说明的是:不需要过度强调孰优孰劣,应在合适的场景下选择合适的数据类型。

简言之,没有不合适的数据类型,只有使用了不合适的场景。

References