Learn python with socratica [My notes] - part 14- Python Tuples

Lesson 16

Introduction

不是所有的数据都能以pile的形式存储,一般情况下,把数据存储成序列更有用。Python提供了几种处理序列的方式,list就是其中一个常见方法,但是tuple是一种更小更快存储方法。那么,list和tuple有那些不同呢?开始做实验吧。

Difference between List and Tuple

第一个小不同,list用方括号定义,而tuple用圆括号定义。

1
2
3
4
5
6
7
8
9
# List example
prime_numbers = [2,3,5,7,11,13,17]

# Tuple example
perfect_squares = (1,4,9,16,25,36) # first difference: [],()

# Display length
print("# Primes = ", len(prime_numbers))
print("# Squares = ", len(perfect_squares))
# Primes =  7
# Squares =  6

我们现在试着打印了list和tuple的序列长度,暂时是没有区别的。下面把元素都打印出来试试。

1
2
3
4
5
6
# Iterate over both sequences
for p in prime_numbers:
print("Prime: ", p)

for n in perfect_squares:
print("Squares: ", n)
Prime:  2
Prime:  3
Prime:  5
Prime:  7
Prime:  11
Prime:  13
Prime:  17
Squares:  1
Squares:  4
Squares:  9
Squares:  16
Squares:  25
Squares:  36

到目前为止,还是看不出来有什么不同。那么我们试着把适用于两个数据结构的内建方法打印出来看看。

1
2
3
4
5
print("List methods")
print(dir(prime_numbers))
print(80*"_")
print("Tuple methods")
print(dir(perfect_squares))
List methods
['__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']
________________________________________________________________________________
Tuple methods
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']

可以发现,List有’append’, ‘clear’, ‘copy’, ‘count’, ‘extend’, ‘index’, ‘insert’, ‘pop’, ‘remove’, ‘reverse’, ‘sort’这些方法,而Tuple只有’count’, ‘index’。这也就意味着List比Tuple要占用更多的存储空间。

1
2
3
4
5
6
7
8
# utilize sys.getsizeof to get the memery
import sys

list_eg = [1,2,3,'a','b','c',True,3.1415]
tuple_eg = (1,2,3,'a','b','c',True,3.1415)

print("list size = ", sys.getsizeof(list_eg))
print("tuple_size = ", sys.getsizeof(tuple_eg))
list size =  128
tuple_size =  112

终于可以看到他们之间的区别了,这一点在数据量很大的时候就显而易见了,Tuple更适合规模大且只需要简单操作存储的数据。

当然,从内建函数中也可以得到,List可以增删改,但是Tuple是不能变的,也可以称之为immutable。Python对牺牲了Tuple的功能,赋予它更快的速度。

1
2
3
4
5
6
7
8
9
10
# utilize timeit to test the speed
import timeit

list_test = timeit.timeit(stmt="[1,2,3,4,5]",
number=1000000)
tuple_test = timeit.timeit(stmt="(1,2,3,4,5)",
number=1000000)

print("List time : ", list_test)
print("Tuple time :", tuple_test)
List time :  0.12573448600005577
Tuple time : 0.02030748099991797

从这个小实验中可以得到,Tuple在速度方面的优势还是很明显的。

Experiment on Tuple

1
2
3
4
5
6
7
8
9
empty_tuple = ()
test1 = ("a")
test2 = ("a", "b")
test3 = ("a", "b", "c")

print(empty_tuple)
print(test1)
print(test2)
print(test3)
()
a
('a', 'b')
('a', 'b', 'c')

为什么test1打印出来是字符串?而不是和其他一样的tuple格式呢?

1
2
print(type(test1))
print(type(test2))
<class 'str'>
<class 'tuple'>

果然是字符串,原因在于当只有一个元素时,需要以逗号结尾。

1
2
test1 = ("a",)
print(test1)
('a',)

Alternative Construction of Tuple

1
2
3
4
5
6
7
8
9
10
11
12
# another way
test1 = 1,
test2 = 1,2
test3 = 1,2,3

print(test1)
print(test2)
print(test3)

print(type(test1))
print(type(test2))
print(type(test3))
(1,)
(1, 2)
(1, 2, 3)
<class 'tuple'>
<class 'tuple'>
<class 'tuple'>

Tuple Assignment

1
2
3
4
5
6
7
8
9
10
# (age, country, know_python)
survey = (23, "China", True)

age = survey[0]
country = survey[1]
know_python = survey[2]

print("Age = ",age)
print("Country = ",country)
print("Know Python? ", know_python)
Age =  23
Country =  China
Know Python?  True

用List同样的方式提取tuple中的元素是有效的,但是tuple提供了更高效的方法。

1
2
3
4
5
6
survey2 = (24, "America", True)
age, country, know_python = survey2

print("Age = ",age)
print("Country = ",country)
print("Know Python? ", know_python)
Age =  24
Country =  America
Know Python?  True

同时也要注意一个错误,这种方式去提取tuple中的元素,一定要一一对应,举个例子:

1
x,y,z = (1,2)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-16-6f419fd02ba5> in <module>()
----> 1 x,y,z = (1,2)


ValueError: not enough values to unpack (expected 3, got 2)
1
a,b,c = (1,2,3,4)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-17-2e0282f2aef3> in <module>()
----> 1 a,b,c = (1,2,3,4)


ValueError: too many values to unpack (expected 3)

Conclusion

以上就是Tuple的内容,与List相比,构建速度很快。需要注意的是如果只有一个元素,要记得以逗号结尾。在用tuple特有的方式提取元素是,注意一一对应,不能多也不能少。总的来说,Tuple是有它的优势的,考虑代码的质量是需要考虑考虑它与List谁更适合自己的子模块。

Youtube source:
https://www.youtube.com/watch?v=bY6m6_IIN94&list=PLi01XoE8jYohWFPpC17Z-wWhPOSuh8Er-