Python Tuple

Back To Index

Tuples

Intoduction to Python Tuples

Python tuples are very similar to lists. They have almost all the same behavior, with a few key exceptions which we’ll touch on here. A tuple is made any time items are separated by a comma. Optionally, they can be surrounded by round parentheses ( ). Tuples can be accessed the same way as lists. Like lists, tuples can have different types of items in them. They can be arbitrarily nested and iterated over just like lists.

But unlike lists, tuples have constant length and their items cannot be changed. We can’t add or delete elements from a tuple. This write protection can be nice for ensuring the integrity of data, and also makes iterating over tuples run faster lists.

In [2]:
myTuple = 'a', 4, True
In [3]:
myTuple
Out[3]:
('a', 4, True)
In [4]:
secondTuple = (2,3,4)

Parentheses also get used for arithmetic, so to tell Python you want a tuple with only one element, it needs a comma.

In [5]:
one_element_tuple = (9,)
In [6]:
one_element_tuple
Out[6]:
(9,)
In [9]:
the_number_nine = (9)
In [10]:
the_number_nine
Out[10]:
9
In [14]:
#Access: 
secondTuple[1], myTuple[-1]
Out[14]:
(3, True)
In [15]:
#Immutability: items cannot be changed
secondTuple[1] = 4
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-c02da4086154> in <module>
      1 #Immutability: items cannot be changed
----> 2 secondTuple[1] = 4

TypeError: 'tuple' object does not support item assignment
In [16]:
#Tuples can be used in list comprehension
list_of_squares = [x*x for x in secondTuple]
print(list_of_squares)
[4, 9, 16]
In [17]:
#We can still make new tuples from old tuples using + and * the way we did for lists
myTuple + secondTuple
Out[17]:
('a', 4, True, 2, 3, 4)
In [20]:
one_element_tuple*5
Out[20]:
(9, 9, 9, 9, 9)

Iteration over tuples

This works the same way as with lists

In [22]:
for a in myTuple:
    print(a)
a
4
True
In [23]:
#The zip function also works with tuples. 
for a,b in zip(myTuple, secondTuple):
    print(a,b)
a 2
4 3
True 4

Multiple assignment

Tuples can be assigned to other tuples. Since a tuple is anything with a comma, this serves as the basis of multiple assignment and multiple return values in python.

In [26]:
#Multiple assignment
print(myTuple)
my_char, some_int, a_bool = myTuple
print(my_char)
print(some_int)
print(a_bool)
('a', 4, True)
a
4
True
In [28]:
#multiple return values from a function
def f(x): #define a little function that returns two numbers: both 2x and x^2
    return 2*x, x*x

two_x, x_squared = f(3) #perform the multiple value return. 

print(two_x, x_squared)
6 9

Named Tuples

One of the nicest things about tuples is they’re easy to convert them into a namedtuple. A namedtuple is something like a struct that behaves like a tuple, but let us access elements by name instead of just by index. They also give us room to label the type of data that’s in the tuple. Namedtuples can be just as memory efficient as tuples since they don’t have a per-instance dictionary.

In [29]:
xy_pair_tuple = (3.1,4.)
In [32]:
import collections #load the collections package, which enables namedtuple's

Here we make make a constructor “Point” for namedtupels of type “point_2D”. The elements of this nametuple have hames “x”, and “y”.

In [39]:
Point = collections.namedtuple("point_2D",["x",'y'])
In [41]:
xy_pair_namedtuple = Point._make(xy_pair_tuple) #make a namedtuple out of our old tuple
In [45]:
#we can still access it like a tuple
xy_pair_namedtuple[1] 
Out[45]:
4.0
In [46]:
#and we can access it by name
xy_pair_namedtuple.y 
Out[46]:
4.0
In [61]:
#we can also unpack a namedtuple the same way we do for tuples. 
x,y = xy_pair_namedtuple
print(x)
print(y)
3.1
4.0
In [56]:
#we can now assign members of the named tuple in order, by name, or a mix of the two. 
second_point = Point(5, y=7) 
print(second_point)
point_2D(x=5, y=7)
In [55]:
#If we assign by name, we don't have to worry about the order.
third_point = Point(y=1, x=3) 
print(third_point)
point_2D(x=3, y=1)
In [52]:
#We can also access the type of the nametuple. This helps us label our data and do things like dimensional analysis. 
type(xy_pair_namedtuple)
Out[52]:
__main__.point_2D
In [72]:
#We can further describe what x and y are by inserting documentation straight into the objects
#by writing to their __doc__
Point.x.__doc__ = "This is the x coordinate of a point in a 2 dimensional Euclidian space, blah blah blah"
print(Point.x.__doc__)
This is the x coordinate of a point in a 2 dimensional Euclidian space, blah blah blah
In [64]:
#ANOTHER EXAMPLE. Here using a comma separated string instead of a list of strings, which python knows how to parse 
#We could just as well have used a space separated string "name age phone_number" 
Person = collections.namedtuple("human","name, age, phone_number")
In [58]:
alice = Person(name = "Alice", phone_number = 8675309, age = 29)
In [59]:
bob = Person(phone_number = 5551234, age = 12, name = "Bob")
In [62]:
for someone in (alice, bob): #iterate over alice and bob
    print("%s is %d years old and their phone number is %d"%someone) 
    #someone unpacks into the string "name" (which goes into %s), the number age, (which goes into the first %d),
    #and the numeric phone number (which goes into the second %d)
Alice is 29 years old and their phone number is 8675309
Bob is 12 years old and their phone number is 5551234

What not to name things in a namedtuples: the names of variables must not conflict with python keywords. So no variable can be named “for” or “class”, and so on. Type names cannot start with a number and cannot contain spaces. They also can’t repeat. Sometimes this can’t be helped and the naming may be out of the control of the programmer. This could happen when representing the rows of a database and loading in the names of the columns. In such cases, turn on “rename”, and python will patch any such problems.

In [79]:
greek_variables = collections.namedtuple('greek', 'alpha beta lambda delta', rename=True) #lambda is a python keyword
greek_variables._fields #list the names of the items in this namedtuple. 
#We see that python detects that "lambda" isn't a valid name and replaces it with "_2" since its at index 2
Out[79]:
('alpha', 'beta', '_2', 'delta')
In [81]:
person_with_2_phones = collections.namedtuple("human","name, age, phone_number, phone_number", rename = True)
person_with_2_phones._fields #python now detects a repeated field name and gives it a new name "_3"
Out[81]:
('name', 'age', 'phone_number', '_3')

Back To Index