In the previous two lessons, we talked about lists in Python. A list is a container-type data type. Through variables of list type, we can store multiple pieces of data and use loops to process data in batches. Of course, Python also has other container-type data types. Next, we will talk about another one, and its name is the tuple.
In Python, a tuple is also a sequence made up of multiple elements in a certain order. The difference between a tuple and a list is that a tuple is an immutable type. This means that once a variable of tuple type has been defined, elements cannot be added or deleted, and the values of the elements cannot be changed either. If you try to modify an element in a tuple, it raises TypeError and causes the program to crash. Tuples are usually defined with literal syntax like (x, y, z), and the operators supported by tuples are the same as those supported by lists. Look at the code below.
# A tuple with three elements.
t1 = (35, 12, 98)
# A tuple with four elements.
t2 = ('Luo Hao', 45, True, 'Chengdu, Sichuan')
# Check the types of the variables.
print(type(t1)) # <class 'tuple'>
print(type(t2)) # <class 'tuple'>
# Check the number of elements in the tuple.
print(len(t1)) # 3
print(len(t2)) # 4
# Indexing
print(t1[0]) # 35
print(t1[2]) # 98
print(t2[-1]) # Chengdu, Sichuan
# Slicing
print(t2[:2]) # ('Luo Hao', 45)
print(t2[::3]) # ('Luo Hao', 'Chengdu, Sichuan')
# Loop through the elements in the tuple.
for elem in t1:
print(elem)
# Membership operations
print(12 in t1) # True
print(99 in t1) # False
print('Hao' not in t2) # True
# Concatenation
t3 = t1 + t2
print(t3)
# Comparison
print(t1 == t3) # False
print(t1 >= t3) # False
print(t1 <= (35, 11, 99)) # FalseIf a tuple has two elements, we call it a 2-tuple. If a tuple has five elements, we call it a 5-tuple. One thing that needs special attention is this: () means the empty tuple, but if a tuple has only one element, then we need to add a comma. Otherwise, () does not mean tuple literal syntax. It means parentheses used to change operator precedence. So ('hello', ) and (100, ) are 1-tuples, while ('hello') and (100) are only a string and an integer. We can verify this with the code below.
a = ()
print(type(a)) # <class 'tuple'>
b = ('hello')
print(type(b)) # <class 'str'>
c = (100)
print(type(c)) # <class 'int'>
d = ('hello', )
print(type(d)) # <class 'tuple'>
e = (100, )
print(type(e)) # <class 'tuple'>When we assign multiple values separated by commas to one variable, the multiple values are packed into a tuple. When we assign one tuple to multiple variables, the tuple is unpacked into multiple values and then assigned to the corresponding variables, as shown below.
# Packing
a = 1, 10, 100
print(type(a)) # <class 'tuple'>
print(a) # (1, 10, 100)
# Unpacking
i, j, k = a
print(i, j, k) # 1 10 100If the number of unpacked values does not match the number of variables, Python raises ValueError, and the error message will be either too many values to unpack or not enough values to unpack.
a = 1, 10, 100, 1000
# i, j, k = a # ValueError: too many values to unpack
# i, j, k, l, m, n = a # ValueError: not enough values to unpackThere is one way to solve the problem when the number of variables is smaller than the number of elements: use a starred expression. With a starred expression, one variable can receive multiple values, as shown below. Two points need attention: first, a variable marked with * becomes a list, and that list can contain 0 or more elements; second, only one starred expression can appear in one unpacking statement.
a = 1, 10, 100, 1000
i, j, *k = a
print(i, j, k) # 1 10 [100, 1000]
i, *j, k = a
print(i, j, k) # 1 [10, 100] 1000
*i, j, k = a
print(i, j, k) # [1, 10] 100 1000
*i, j = a
print(i, j) # [1, 10, 100] 1000
i, *j = a
print(i, j) # 1 [10, 100, 1000]
i, j, k, *l = a
print(i, j, k, l) # 1 10 100 [1000]
i, j, k, l, *m = a
print(i, j, k, l, m) # 1 10 100 1000 []One more thing should be explained: unpacking syntax works for all sequences. This means the lists we talked about before, range sequences built by the range function, and even strings can all use unpacking syntax. Try running the code below and see what result you get.
a, b, *c = range(1, 10)
print(a, b, c)
a, b, c = [1, 10, 100]
print(a, b, c)
a, *b, c = 'hello'
print(a, b, c)Swapping the values of variables is a very common operation when writing code. But in many programming languages, swapping the values of two variables requires an intermediate variable. If you do not use an intermediate variable, then you need to use rather obscure bitwise operations. In Python, swapping the values of variables a and b only needs the code below.
a, b = b, aSimilarly, if you want to rotate the values of three variables a, b, and c, so that the value of b is assigned to a, the value of c is assigned to b, and the value of a is assigned to c, it can be done in the same way.
a, b, c = b, c, aIt should be explained that the operations above do not use packing and unpacking syntax. Python bytecode has instructions such as ROT_TWO and ROT_THREE that can do this operation directly, so the efficiency is very high. But if the values of more than three variables need to be rotated in order, then there is no directly usable bytecode instruction, and we have to complete the swap through packing and unpacking.
There is another question here that is worth discussing. Python already has the list type, so why do we still need tuples? This question may seem a little difficult for beginners, but it does not matter. Let us first put forward the idea, and everyone can keep learning and understand it gradually.
- Tuples are immutable, and immutable types are more suitable for multi-threaded environments, because they reduce the synchronization cost of concurrent access to variables. We will discuss this point later when we talk about concurrent programming.
- Tuples are immutable, and usually immutable types are faster to create than the corresponding mutable types. We can use the
timeitfunction in thetimeitmodule to see how much time it takes to create a tuple and a list that hold the same elements. Thenumberparameter of thetimeitfunction means how many times the code is executed. In the code below, we create a list and a tuple that both store the integers from1to9, and each operation runs10000000times.
import timeit
print('%.3f seconds' % timeit.timeit('[1, 2, 3, 4, 5, 6, 7, 8, 9]', number=10000000))
print('%.3f seconds' % timeit.timeit('(1, 2, 3, 4, 5, 6, 7, 8, 9)', number=10000000))Output:
0.635 seconds
0.078 seconds
Note: The result of the code above will be different on different hardware and software systems. On the computer I am using now, creating the list
10000000times takes0.635seconds, while creating the tuple10000000times takes0.078seconds. Clearly, creating a tuple is faster, and the time difference is about one order of magnitude. You can run this code on your own computer and compare the results.
Of course, tuples and lists in Python can be converted into each other. We can do that with the code below.
infos = ('Luo Hao', 45, True, 'Chengdu, Sichuan')
# Convert the tuple to a list.
print(list(infos)) # ['Luo Hao', 45, True, 'Chengdu, Sichuan']
frts = ['apple', 'banana', 'orange']
# Convert the list to a tuple.
print(tuple(frts)) # ('apple', 'banana', 'orange')Lists and tuples are both container-type data types, which means one variable can store multiple pieces of data, and they are both ordered containers that organize elements in a certain order. Lists are mutable data types, while tuples are immutable data types, so lists can add elements, delete elements, clear elements, sort, and reverse, but these operations do not work for tuples. Lists and tuples both support concatenation, membership operations, indexing, and slicing. The string type that we will talk about later also supports these operations, because a string is also a sequence made up of characters in a certain order. In this respect, there is no difference between the three. We recommend that everyone use list comprehension syntax to create lists. It is not only easy to use, but also very efficient, and it is one of the very distinctive pieces of syntax in Python.