CodingBison

Tuples hold a sequence of data elements. In this regard, they are similar to lists. However, unlike lists, tuples are immutable -- in other words, elements of tuples cannot be modified. Thus, we can neither update individual elements nor delete them!

We can define a tuple using a pair of parenthesis and add elements by separating them with a comma. Like lists, we can access elements of a tuple using their indices. Please recall that we use square brackets ([,]) for lists and braces ({,}) for dictionaries.

We provide an example that defines a tuple and accesses its elements.

 [user@codingtree]$ python3
 Python 3.2.3 (default, Jun  8 2012, 05:40:06) 
 [GCC 4.6.3 20120306 (Red Hat 4.6.3-2)] on linux2
 Type "help", "copyright", "credits" or "license" for more information.
 >>> 
 >>> varTup = (101, "tiger", "zebra", 237)
 >>> 
 >>> print(type(varTup))
 <class 'tuple'>
 >>> 
 >>> print(varTup)
 (101, 'tiger', 'zebra', 237)
 >>> 
 >>> print(varTup[1])
 tiger
 >>> 

If we want to define a tuple with only one element, then we can put a comma followed by nothing. Without a comma, the type may not be tuple. Here is an example:

 >>> varTup=(101)
 >>> print(type(varTup))
 <class 'int'>
 >>> 
 >>> print(varTup)
 101
 >>> 
 >>> varTup=(101,)
 >>> print(type(varTup))
 <class 'tuple'>
 >>> 
 >>> print(varTup)
 (101,)
 >>> 

Since tuples are immutable, its elements cannot be modified. And, if we try to modify, then Python will throw an error. However, the immutable part is only for high-level elements -- if the tuple holds a mutable element (like lists), then it is okay to modify that list. In the following example, we use the "del" operator to delete elements of a list that is present in the tuple.

 >>> varTup = (101, ["tiger", "zebra"], 237)
 >>> 
 >>> print(varTup[0])
 101
 >>> 
 >>> varTup[0] = 680
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: 'tuple' object does not support item assignment
 >>> 
 >>> varTup[1][0] = "blue whale"
 >>> 
 >>> print(varTup)
 (101, ['blue whale', 'zebra'], 237)
 >>> 
 >>> del varTup[1][0]
 >>> del varTup[1][0]
 >>> 
 >>> print(varTup)
 (101, [], 237)
 >>> 

Tuple Methods

We can use the dir() function to see various attributes (methods) of a tuple. We provide its output below. The provided output shows two callable methods: count() and index(). Note that the attributes that have starting and trailing double underscores are not callable.

 >>> varTup = (101,)
 >>> 
 >>> dir(varTup) 
 ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', 
 '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', 
 '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', 
 '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', 
 '__subclasshook__', 'count', 'index']
 >>> 

Method index() and count() for tuples behave similar to that of lists. Method index(x) returns the first occurrence of the object x in the tuple. This method takes two additional (optional) arguments as in index(x, i1, i2). If we specify just i1 as in index(x, i1), then this means that index() searches for x starting (and including) the index i1. If we specify both i1 and i2 as in index(x, i1, i2), then this means that index() searches for x starting (and including) the index i1 but less than (and excluding) the index i2. The method count(x) returns the number of occurrences of the object x in the tuple.

Here is an example that demonstrates these two methods.

 >>> varTup = (101, "tiger", "zebra", "tiger", 237, "tiger")
 >>> print(varTup)
 (101, 'tiger', 'zebra', 'tiger', 237, 'tiger')
 >>> 
 >>> varTup.index("tiger")
 1
 >>> varTup.index("tiger", 4)
 5
 >>> varTup.index("tiger", 2, 4)
 3
 >>> varTup.count("tiger")
 3
 >>> 

Comparing Lists and Tuples

Both lists and tuples allow us to store a sequence of data. So, why does Python support two types for the same purpose? The answer to this question revolves around the fact that tuples are immutable but lists are not. This has advantages of its own.

First, we can use tuples as keys for dictionaries since keys for dictionaries must be immutable. This can come in handy for cases where we would like to store values for properties that use multiple data types as keys. As an example, if we were to store certain property (value) based on X,Y coordinates, then we can use a tuple for the associated (X,Y) coordinates. With lists, this would not be possible!

The following example demonstrates that we can use two tuples as keys for a dictionary. However, when we attempt to add a list as a key, then Python throws an error.

 >> varDict = {}
 >>> 
 >>> #Create a tuple based on (x,y) co-ordinate and use it as a key.
 ... tupKey1 = (10.0, 20.0)
 >>> varDict[tupKey1] = 30.0
 >>> 
 >>> #Create another tuple based on (x,y) co-ordinate and also use it as a key.
 ... tupKey1 = (20.0, 40.0)
 >>> varDict[tupKey1] = 60.0
 >>> 
 >>> print(varDict)
 {(10.0, 20.0): 30.0, (20.0, 40.0): 60.0}
 >>> 
 >>> #Try the same with a list!
 >>> listKey = [10.0, 20.0]
 >>> varDict[listKey] = 30.0
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: unhashable type: 'list'
 >>> 

Second, since tuples can not be changed and as in Python, we pass parameters to a function by a copy of the reference, this means that we can be certain that if we pass a tuple to a function, then the tuple can not be modified within the function. This is not the case with lists. Since lists are mutable, when we pass a list to a function, it can be changed within the function. Now, since we pass a copy of the reference of the list, if we modify the list, then once the function call is complete, the reference still holds the list and any modification inside the function will be visible after the call.

Here is an example that shows that if we modify the value of a list element, then that becomes visible once the function call is completed. Python will simply throw an error if we attempt to change the value of the tuple.

 >>> def funcFoo(passedList):
 ...     passedList[1] = 680
 ... 
 >>> varList = [101, 5, 15]
 >>> print(varList)
 [101, 5, 15]
 >>> 
 >>> #Call the function.
 >>> funcFoo(varList)
 >>> print(varList)
 [101, 680, 15]
 >>> 

In terms of usage, lists are typically used for storing homogeneous data where as tuples are used for storing heterogeneous data. Tuples (as in a database table) can be used to store records where each element of the record can hold different data types. For example, we can have tuple that holds name, age, and height of users: ("John Doe", 26, 5.11).

This allows us to have a tuple that can hold heterogeneous data but then a list that stores the same type of tuples has homogeneous data. Note that this style of usage has nothing to do with the fact that tuples are immutable where as lists are not.





comments powered by Disqus