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.
myTuple = 'a', 4, True
('a', 4, True)
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.
one_element_tuple = (9,)
the_number_nine = (9)
#Access: secondTuple, myTuple[-1]
#Immutability: items cannot be changed secondTuple = 4
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-15-c02da4086154> in <module> 1 #Immutability: items cannot be changed ----> 2 secondTuple = 4 TypeError: 'tuple' object does not support item assignment
#Tuples can be used in list comprehension list_of_squares = [x*x for x in secondTuple] print(list_of_squares)
[4, 9, 16]
#We can still make new tuples from old tuples using + and * the way we did for lists myTuple + secondTuple
('a', 4, True, 2, 3, 4)
(9, 9, 9, 9, 9)
for a in myTuple: print(a)
a 4 True
#The zip function also works with tuples. for a,b in zip(myTuple, secondTuple): print(a,b)
a 2 4 3 True 4
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.
#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
#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)
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.
xy_pair_tuple = (3.1,4.)
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”.
Point = collections.namedtuple("point_2D",["x",'y'])
xy_pair_namedtuple = Point._make(xy_pair_tuple) #make a namedtuple out of our old tuple
#we can still access it like a tuple xy_pair_namedtuple
#and we can access it by name xy_pair_namedtuple.y
#we can also unpack a namedtuple the same way we do for tuples. x,y = xy_pair_namedtuple print(x) print(y)
#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)
#If we assign by name, we don't have to worry about the order. third_point = Point(y=1, x=3) print(third_point)
#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)
#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
#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")
alice = Person(name = "Alice", phone_number = 8675309, age = 29)
bob = Person(phone_number = 5551234, age = 12, name = "Bob")
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.
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
('alpha', 'beta', '_2', 'delta')
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"
('name', 'age', 'phone_number', '_3')