Python Tuple in Depth

diving into python tuple

“black and gray laptop computer turned on” by Markus Spiske on Unsplash

Content:

  1. Introduction
  2. Advantages
  3. Basic Operations
  4. Magic
  5. How to Boost Performance with Tuples
  6. Conclusion

Introduction

Tuple is one of python data types that categorize as sequence and it consists of comma-separated objects like string, number, list and even another tuple. Tuple is immutable, and that’s differ it from list. Here is some example to create a tuple:

# Example 1
>>> x = ("1", 2, [3])
>>> print(x)
('1', 2, [3])
>>> type(x)
tuple
# Example 2
>>> a = "1"
>>> b = 2
>>> c = [3]
>>> y = a, b, c
>>> print(y)
('1', 2, [3])
>>> type(y)
tuple
# Example 3 - trick for create a tuple that consists only one object.
>>> a = "1"
>>> y = (a)
>>> type(y)
str
>>> a = "1"
>>> y = (a,)
>>> type(y)
tuple
>>> print(y) # When you print it will show the comma
('1',)
>>> print(y[1]) # But when you want to get the blank after comma, it will throw an error. So don't worry, it still consists of one object.
IndexError: tuple index out of range
>>> len(y)
1

Advantages

>>> from dis import dis
>>> def createList():
x=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y=x[5]
>>> def createTuple():
x=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
y=x[5]
>>> dis(createList)
2 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (2)
4 LOAD_CONST 3 (3)
6 LOAD_CONST 4 (4)
8 LOAD_CONST 5 (5)
10 LOAD_CONST 6 (6)
12 LOAD_CONST 7 (7)
14 LOAD_CONST 8 (8)
16 LOAD_CONST 9 (9)
18 LOAD_CONST 10 (10)
20 BUILD_LIST 10
22 STORE_FAST 0 (x)

3 24 LOAD_FAST 0 (x)
26 LOAD_CONST 5 (5)
28 BINARY_SUBSCR
30 STORE_FAST 1 (y)
32 LOAD_CONST 0 (None)
34 RETURN_VALUE
>>> dis(createTuple)
6 0 LOAD_CONST 11 ((1, 2, ... , 9, 10))
2 STORE_FAST 0 (x)

7 4 LOAD_FAST 0 (x)
6 LOAD_CONST 5 (5)
8 BINARY_SUBSCR
10 STORE_FAST 1 (y)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
  • Can assign as key at dictionary. Looks like not an advantage right? I will show you the implementation later.
  • Write protected (Absolutely, tuple is immutable).
  • Use less memory than list. Because, tuple is fixed-size and list is variable-sized.
>>> [1].__sizeof__()
48
>>> (1).__sizeof__()
28
>>> [1, 2, 3, 4 ,5 ,6, 7, 8, 9, 10].__sizeof__()
120
>>> (1, 2, 3, 4 ,5 ,6, 7, 8, 9, 10).__sizeof__()
104

Basic Operations

  • Accessing Values

We can access the values by using their index directly or slicing. Basically we just play with index values inside the square brackets. The index will start at zero and ended with n-1, where n is the length of tuple. Access via slicing will be different because it use this format “var[from:until+1]”. Here some example of accessing values in tuple:

>>> x = (1, 2, 3, 4, 5)
>>> x[0] # access first item
1
>>> x[len[x]-1] # access last item
5
>>> x[0:] # access all item from beginning
(1, 2, 3, 4, 5)
>>> x[3:] # access all item from index 3 (remember that index start from zero)
(4, 5)
>>> x[1:3] # we want to access from index 1 to 2.
(2, 3)
>>> x[:3] # we want to access from beginning to index 2
(1, 2, 3)
  • Concatenation

We can concatenate tuples. Wait, what!? Tuple is immutable right? The answer is YES. Tuple is immutable, when we concatenate two or more tuples, it will have different id. That mean, we create a new tuple that contain tuple A + tuple B. Let see the example below:

>>> a = (1, 2, 3)
>>> id(a) # the id can be different from yours
85656488
>>> b = (4, 5, 6)
>>> id(b)
85657496
>>> c = a + b
>>> id(c)
7966832
>>> print(c)
(1, 2, 3, 4, 5, 6)
Spoiler Alert: we will see more about id in magic section.
  • Multiply

Multiply mean that we duplicate n times of the tuple. When you have a tuple consists of string (“A”). Then multiply it by two will make the tuple contains (“A”, “A”). The concept is same with concatenation, it will create a new tuple. Here is the example of tuple multiplying:

>>> x = ("A",)
>>> x = x * 2
>>> print(x)
('A', 'A')
  • Delete Tuple

Since it was immutable, so we can’t delete an item in tuple. What we can do is delete the whole tuple. To delete a tuple, simply use “del”. Here the example:

>>> x = ("A", "B")
>>> del x[0]
TypeError: 'tuple' object doesn't support item deletion
>>> del x
>>> print(x) # variable x is gone :D
NameError: name 'x' is not defined
  • The difference between “is” and “==”

There is some ways to compare tuples. The first one is use “is”, it will compare tuples by their id. When a tuple have same id, it must have same items too. Then the second is “==”, this only compare tuples by their items. When tuples have same items then return true, same items doesn’t mean have same id. I will try to show you the different:

>>> print((1, 2) == (1, 2))
True
>>> print((1, 2) is (1, 2))
False
>>> x = (1, 2)
>>> y = x
>>> print(x is y and x == y)
True
  • Use “in” to check if an items is exists

How to find an item in tuple? Then using “in” is the answer. This will try to figure out if a tuple contains some values or not. Here the example:

>>> x = (1, 2)
>>> print(1 in x)
True
>>> print("1" in x)
False
>>> print(3 in x)
False
>>> print((1 and 2) in x)
True
>>> print((1 or 4) in x)
True
>>> print((1 and 3) in x)
False
  • Return maximum or minimum value of items in a tuple

How about to find maximum or minimum value? We can do it easily here, with max or min. Here the example:

>>> max((1, 2))
2
>>> min((1, 2))
1
>>> max((1, 2.1))
2.1
>>> max(("1", 2))
TypeError: '>' not supported between instances of 'int' and 'str'
Notes: you must have a tuple with values that have same data types, you can’t compare number with string.
  • Sort item in tuple

Then, how to sort? Are this can be easily achieved? Yes. With the power of “sorted”, we can easily sort values in tuple ascending or descending. Default sorting type is ascending, add “reverse=True” when we want to sort it descending.

>>> sorted(("1","3","2"), reverse=True)
['3', '2', '1']
>>> sorted(("1","3","2"))
['1', '2', '3']
>>> sorted((1, "2", "3"))
TypeError: '<' not supported between instances of 'str' and 'int'
Notes: the rule is same as max or min

Magic

Let’s the magic begin:

>>> x = ("1", 2, [3])
>>> print(x)
('1', 2, [3])
>>> y = x[2]
>>> y.append(4)
>>> y.append(5)
>>> y.append(6)
>>> print(x)
('1', 2, [3, 4, 5, 6])

Aha! Its changed. Tuple is immutable, but its only the structure. Its consists of object id references and if the object referenced is mutable, then that object can be changed. Please check the code and image below to see how its work:

>>> x = ("1", 2, [3])
>>> print(id(x))
85100512
>>> print(id(x[2]))
85133000
>>> y = x[2]
>>> print(id(y))
85133000
>>> y.append(4)
>>> print(y)
85133000
>>> print(x)
('1', 2, [3, 4])
>>> print(id(x))
85100512
Tuple is consists of object id references

For further read, see this nice article from Luciano Ramalho.

How to Boost Performance with Tuples

Then, how tuple can boost performance? I will give you one example. Since its immutable, it can be set as key for dictionary right? So, what if i use that dictionary as cache? Here the example:

>>> import time
>>> def complex_function(a, b):
key = (a, b)
if key not in cache:
# pretend like complicated code
time.sleep(5)
cache.update({key: a+b})
return cache[key]
>>> cache = {}
>>> start = time.time()
>>> print(complex_function(5,1))
6
>>> end = time.time()
>>> print(end - start)
5.001500129699707
>>> start = time.time()
>>> print(complex_function(5,1))
6
>>> end = time.time()
>>> print(end - start)
0.0030002593994140625
>>> print(cache)
{(5, 1): 6}

When a function called, we can save the input parameter and result. Then if we call that function with same parameter, it will get the result directly from dictionary. So, we didn’t need to recalculate same result.

Conclusion

Tuple maybe a simple and forgotten python’s data type. But, its have a lot of great features. So, lets start to use and discover more. If you want to read my article about variables, then go here. Claps if this article help you and feel free to ask me.