Python Tuples
In the previous two lessons, we introduced Python lists, which are container-type data types. Through list-type variables, we can store multiple data items and implement batch operations on data through loops. Of course, Python has other container-type data types. Next, we’ll introduce another container-type data type called tuple.
Tuple Definition and Operations
In Python, a tuple is also a sequence composed of multiple elements arranged in a certain order. The difference between tuples and lists is that tuples are immutable types, which means that once a tuple-type variable is defined, the elements cannot be added or deleted, and the values of elements cannot be modified. If you try to modify elements in a tuple, it will raise a TypeError error, causing the program to crash. Tuples are typically defined using literal syntax like (x, y, z). Tuples support the same operators as lists. Let’s look at the code below.
# Define a three-element tuple
t1 = (35, 12, 98)
# Define a four-element tuple
t2 = ('Luo Hao', 45, True, 'Chengdu, Sichuan')
# Check the type of variables
print(type(t1)) # <class 'tuple'>
print(type(t2)) # <class 'tuple'>
# Check the number of elements in tuples
print(len(t1)) # 3
print(len(t2)) # 4
# Indexing operations
print(t1[0]) # 35
print(t1[2]) # 98
print(t2[-1]) # Chengdu, Sichuan
# Slicing operations
print(t2[:2]) # ('Luo Hao', 43)
print(t2[::3]) # ('Luo Hao', 'Chengdu, Sichuan')
# Loop through elements in 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 operations
t3 = t1 + t2
print(t3) # (35, 12, 98, 'Luo Hao', 43, True, 'Chengdu, Sichuan')
# Comparison operations
print(t1 == t3) # False
print(t1 >= t3) # False
print(t1 <= (35, 11, 99)) # False
If a tuple has two elements, we call it a two-tuple; if a tuple has five elements, we call it a five-tuple. It’s important to note that () represents an empty tuple, but if a tuple has only one element, you need to add a comma. Otherwise, () doesn’t represent tuple literal syntax, but rather parentheses that change operation precedence. So ('hello', ) and (100, ) are one-tuples, while ('hello') and (100) are just 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'>
Packing and Unpacking Operations
When we assign multiple comma-separated values to a variable, the multiple values are packed into a tuple type; when we assign a tuple to multiple variables, the tuple is unpacked into multiple values and then assigned to the corresponding variables, as shown in the code below.
# Packing operation
a = 1, 10, 100
print(type(a)) # <class 'tuple'>
print(a) # (1, 10, 100)
# Unpacking operation
i, j, k = a
print(i, j, k) # 1 10 100
When unpacking, if the number of unpacked elements doesn’t match the number of variables, it will raise a ValueError exception with error messages: too many values to unpack (too many values to unpack) or not enough values to unpack (not enough values to unpack).
a = 1, 10, 100, 1000
# i, j, k = a # ValueError: too many values to unpack (expected 3)
# i, j, k, l, m, n = a # ValueError: not enough values to unpack (expected 6, got 4)
There’s a solution when the number of variables is less than the number of elements: use a starred expression. Through starred expressions, we can let one variable receive multiple values, as shown in the code below. Two things to note: first, a variable modified with a starred expression becomes a list with 0 or more elements; second, in unpacking syntax, a starred expression can only appear once.
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 []
It should be noted that unpacking syntax works for all sequences, which means that lists, range sequences constructed by the range function, and even strings can all use unpacking syntax. You can try running the code below to see what results appear.
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 Variable Values
Swapping variable values is a frequently used operation when writing code. In many programming languages, swapping the values of two variables requires an intermediate variable. If you don’t use an intermediate variable, you need to use rather obscure bitwise operations. In Python, swapping the values of two variables a and b only requires the code shown below.
a, b = b, a
Similarly, if you want to swap the values of three variables a, b, c, i.e., assign the value of b to a, the value of c to b, and the value of a to c, you can do the same.
a, b, c = b, c, a
It should be noted that the operations above don’t use packing and unpacking syntax. Python’s bytecode instructions have instructions like ROT_TWO and ROT_THREE that can directly implement this operation with very high efficiency. However, if there are more than three variables whose values need to be swapped in sequence, there are no directly available bytecode instructions, and you need to complete the value swapping between variables through packing and unpacking.
Comparing Tuples and Lists
There’s a very worthwhile question to discuss here: Python already has the list type, so why do we need a type like tuples? This question seems a bit difficult for beginners, but it doesn’t matter. Let’s present the viewpoints first, and you can gradually understand them as you learn.
-
Tuples are immutable types, and immutable types are more suitable for multi-threaded environments because they reduce the synchronization overhead of concurrent access to variables. We’ll discuss this point together when we cover concurrent programming later.
-
Tuples are immutable types, and typically immutable types are superior to corresponding mutable types in creation time. We can use the
timeitfunction from thetimeitmodule to see how much time it takes to create tuples and lists that store the same elements. Thenumberparameter of thetimeitfunction indicates the number of times the code is executed. In the code below, we created lists and tuples storing integers from1to9, executing each operation10000000times and recording the execution time.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 secondsNote: The execution results of the code above vary depending on hardware and software systems. On the computer I’m currently using, executing the list creation operation
10000000times takes0.635seconds, while executing the tuple creation operation10000000times takes0.078seconds. Creating tuples is clearly faster, and there’s an order of magnitude difference in time. You can execute this code on your own computer and post your execution results in the comments to see whose computer is more powerful.
Of course, Python’s tuple and list types can be converted to each other. We can complete this operation through the code below.
infos = ('Luo Hao', 43, True, 'Chengdu, Sichuan')
# Convert tuple to list
print(list(infos)) # ['Luo Hao', 43, True, 'Chengdu, Sichuan']
frts = ['apple', 'banana', 'orange']
# Convert list to tuple
print(tuple(frts)) # ('apple', 'banana', 'orange')
Summary
Both lists and tuples are container-type data types, meaning one variable can store multiple data items, 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 don’t apply to tuples. Both lists and tuples support concatenation operations, membership operations, indexing operations, slicing operations, and other operations. The string type we’ll cover later also supports these operations because strings are sequences of characters arranged in a certain order, and in this respect, the three are no different. We recommend using list comprehension syntax to create lists - it’s not only easy to use but also very efficient, and it’s a very distinctive syntax feature of the Python language.