Tuples in Python - why to use them (and how you might create them on accident!)

In Python, tuples are sequences of objects, very much like lists.

Visually, tuples are defined with parentheses () instead of square brackets [] like lists.

Functionally tuples, unlike lists, are immutable — this means that once you create it, you can’t change it. You can’t add anything to or remove anything from it, and you can’t change the value at a given index. Nothing!

So why would you want this? Let’s look at some ideas below. 👇

Maybe. The internet tells me they are. I tried to prove it to you, but I couldn’t.

I created a list and a tuple, each containing the numbers 0 through 999, and looped through them 100k times. With both, it took just under 1.5 seconds. If anything, the list was faster, though not significantly so.

If speed is the only reason you have for using a tuple, it’s probably not worth it. That said, if you’re able to build a test that proves tuples are faster, I’d love to hear about it, my example may have been too simplistic!

Cool, what does that mean? Well, have you ever tried using a list as the key in a dictionary? You can’t. If you try, you’ll see an error that looks like this: TypeError: unhashable type: ‘list’.

You can, however, assign a tuple as a key in a dictionary. I’m not totally sure what the use case is for this, but there are lots of use cases out there I haven’t thought of!

To me, this is the most compelling reason to use a tuple. Because tuples are immutable (unchangeable), if you know that the contents of a variable should never change, defining it as a tuple instead of a list is an easy way to prevent your future self or other developers from trying to change it down the line - you can’t. I’m a big fan of saving my future self from my current self!

namedtuples are super cool, and are a subclass of tuple. I’m not going to go into enough depth here to totally do them justice, but you can read more about them in the docs, here!

The short version is, namedtuples give you the ability to predefine attributes, or fields, that are “accessible by attribute lookup as well as being indexable and iterable.”

So what does that mean? Here’s an example:

>>> from collections import namedtuple
>>> person = namedtuple('Person', 'first_name, last_name')
>>> adrienne = person(first_name="Adrienne", last_name="Domingus")
>>> adrienne.first_name
'Adrienne'
>>> adrienne.last_name
'Domingus'

You can definitely accomplish this same thing with a dictionary or a class, this is just a somewhat cleaner or interface that might map more easily to other languages you’re familiar with.

For the most part, tuples are defined in the exact same way as lists, just using parentheses instead of square brackets.

my_tuple = (1, 2, 3)

The main thing to look out for is if you need to define a tuple with a single item in it, you need to include a trailing comma, otherwise you’ll just end up with the thing you tried to define inside the tuple, but it won’t actually be a tuple. Like so:

>>> my_tuple = (1)
>>> my_tuple
1
>>> my_tuple = (1,)
>>> my_tuple
(1,)

Even more than defining, accessing items in a tuple is just like a list: you can loop through them or access items based on their index:

>>> my_tuple = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> my_tuple[2]
2
>>> my_tuple[:5]
(0, 1, 2, 3, 4)
>>> my_tuple[4:]
(4, 5, 6, 7, 8, 9)
>>> my_tuple[4:6]
(4, 5)
>>> for num in my_tuple:
...    print(num)
...
0
1
2
3
4
5
6
7
8
9

You can’t!

I’ll be honest, this behavior was really the thing that prompted me to write this post. I’ve been bitten by it before, and one of my teammates was blocked by it this week until I was able to come at it with a fresh set of eyes and point it out.

Take a look at this line of code:

my_name = “Adrienne”,

You probably know what to expect, since you’re reading a post about tuples, but to folks who are new to Python, or just moving quickly and you paste a line in from somewhere else in the codebase (something that used to be a dictionary, perhaps?), it’s easy to miss. If we evaluate my_var, we’ll get back (“Adrienne”,) — a tuple, not a string.

Python’s trying to be helpful. Since as we discussed above, (“Adrienne”), without the trailing ”,”, will end up as just a string, rendering the parentheses meaningless, Python assumes that if you do add that trailing comma, well, you must mean you want a tuple!

So there you have it — tuples appearing in unexpected places? See if the line has a trailing comma! 🔎