Tuple is not just an immutable list

All too often I see people referring to tuple as an immutable list. Also many tutorials on Python present tuples just as a list that cannot be changed. Although it is true that tuple is immutable, there is actually much more to it. 

When I think of a tuple, I like to think of it as a data structure that has meaningful positional arguments.

Consider this code

t = (182, 89, 34)

This is a tuple holding three numbers. If I don't tell you more, these just seem as random numbers with not much meaning. But if I tell you that the first figure represents height, the second represents the weight and the third represents age, suddenly things get much clearer.

This is essentially the idea behind the immutability. The tuples hold data in a particular order for a reason, nothing can be added or deleted, and the positions cannot be changed. That is why when returning multiple arguments from a function, they are returned as a tuple because normally you do not want the return result to be changed in any way.

Both tuple and list can hold homogeneous or heterogeneous data. Often, lists tend to contain homogenous data, tuple, on the other hand, tend to contain heterogeneous data.

t = ('Prague', 'CZ', 1_450_000)

It is quite clear what this tuple hold, it is a representation of a city.  The first two arguments are strings, the last one is an int. It holds the name of the city, the state, and the population. The position gives the meaning of these three pieces of data. In our program, we can establish a convention that all the cities will have these three pieces of data in this particular order and we have a nice data structure. In a way, it is similar to a light-weighted class. 

The downside of it compared to a class is that the positional arguments do not have any names. Sometimes we do need a name for more expressivity. That is where namedtuple comes in.

Having this tuple

prague = ('Prague', 'CZ', 1_450_000)

When I want to reference the population, I need to do this:

prague[2]

If the tuple is small, it is not a big deal, but if I have a tuple holding ten elements, things could go really bad. I have to all the time remember the index of the position and it is error-prone. A much better way would be to write it in a class-like syntax.

prague.population

In order to that, I can either code a simple class (not recommended) or use the previously mentioned build-in namedtuple module. Here is how it works.

from collections import namedtuple
City = namedtuple("City", ["name", "state", "population"])
prague = City("Prague", "CZ", 1_450_000)
prague.population # prints 1 450 000

Namedtuples subclass tuple and add an additional layer to assign property names to the positional argument. They are class factories generating new types. The way they work is quite interesting and I will say more about it in another post because there is far more to cover. 

The point in here was to show, that tuples are more than just an immutable list, they are data structures holding (often heterogenous) pieces of data where the order and the position matters a lot.