Understanding tuples vs. lists in Python
Python has two seemingly similar sequence types, tuples and lists.
The difference between the two that people notice right away, besides literal syntax (parentheses vs. square brackets), is that tuples are immutable and lists are mutable. Unfortunately, because this distinction is strictly enforced by the Python runtime, some other more interesting differences in application tend to get overshadowed.
One common summary of these more interesting, if subtle, differences is that tuples are heterogeneous and lists are homogeneous. In other words:
- Tuples (generally) are sequences of different kinds of stuff, and you deal with the tuple as a coherent unit.
- Lists (generally) are sequences of the same kind of stuff, and you deal with the items individually.
What are these “kinds of stuff” I’m talking about? Types? Sometimes. But types may not tell the whole story.
Consider the following two data structures:
>>> import time
>>> time.localtime()
(2008, 2, 5, 11, 55, 34, 1, 36, 0)
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The first one, a tuple, is a sequence in which position has semantic value. The first position is always a year. This tuple functions as a lightweight record or struct.
The second one, a list, is a sequence where we may care about order, but where the individual values are functionally equivalent.
It’s easy to imagine adding or removing items from the second one without breaking code that handles it or creating something undefined; for the first one, not so much.
A great example of the complementary use of both types is the Python DB API’s fetchmany()
method, which returns the result of a query as a list of tuples. The result set as a whole is a list, because rows are functionally equivalent (homogeneous); the individual rows are tuples, because rows are coherent, record-like groupings of (heterogeneous) column data.
A side note: Many functional languages, including Haskell and OCaml, have a similar distinction that is strictly enforced. Studying one of these languages may help clarify what I’m saying here; it certainly clicked for me when I started playing with Haskell.
There is considerable overlap in the ways tuples and lists can be used, but the built-in capabilities of the two structures highlight some of the above distinctions. For example, tuples have no ‘index’ method for identifying the position at which a particular value is found.
I’ve found that keeping the above distinctions in mind has helped me in my Python programming. Hopefully this attempt at clarification will help others too.
Anja Skrba has translated this post into Croatian. Cool
Lorenzo Bolognini commented :
The best thing I heard about the distinction of tuples vs. lists is that tuples have identity.
You would use tuples to represent a point (x,y): that alone already gives away the big semantic difference between tuples and lists and helps clarify that they are not just read-only lists.
In Django they’re often used to represent, inside a list, an (id, value) pair that you can use in a Select widget.
Have a look at this post and the comment by Jayson Vantuyl.
L.
Chuck commented :
The other nice side effect of tuples is that since the are immutable, they can be used as keys in dictionaries.
Jim Storch commented :
When people ask me about this I usually start my explanation with this abstraction:
Use a list when you need a bucket to put stuff in; “How can I get all these bricks to the roof?”
Use a tuple when you need a bucket of stuff; “Hope you enjoy this fruit basket.”
Vroo commented :
Sorry, this is wrong. Tuples and lists may be either heterogeneous or homogeneous. (1,2), (1,‘b’), [1,2] and [1,‘b’] are all valid as are things like [1,(2,3)]. While it may be the case that some developers use tuples for heterogeneous sets and others use lists for homogeneous sets, it’s misleading to say that’s the difference between the two.
The difference really is that lists are mutable. You can change the values in a list, append to it and delete values in it. You can’t do that to a tuple.
Paul commented :
Vroo – perhaps my use of the word “are” in my third paragraph made things sound too definitive. I’m not claiming to describe “the” difference between the two types; I address the obvious mutable/immutable distinction up front.
What I’m attempting to describe in this post is a common (and in my opinion valuable) convention that is easy to miss when one is first learning Python.
rae commented :
I think I’m starting to grasp the idea of tuples and lists. This might be a stupid question (I’m a newbie programmer), but I’m a bit confused as to in what conditions would you choose to use tuple over a list (since tuples are immutable, lists sound to be more useful maybe?) Also, you mentioned that tuples can be more efficient, can you give a case for this? Thanks!
Shaggs commented :
Thanks for the great page. As a C programmer learning python, I found the description given in the page to be very helpful - “I get it”!
Titus Barik commented :
Looks like one of your links is dead. The link to “Why are there separate tuple and list data types?” now returns a 404.
Momus commented :
Another case of an explanation which explains nothing.
I believe you that tuples and lists are used most often as you say. But WHY is missing!!
To give a true understanding one must specify how Python deals with those types. My guess (as a 2dn day Python “user”), is that tuples are are stored and/or accessed more efficiently. Which would be a good reason to use them if objects are immutable.
Years ago, when learning C++ I found only one book to be truly useful, by Stroustrup’s C++ Reference Manual. Because n the book Stroustrup would give suggestion as to how each feature would be implemented by a compiler. This is the only way to give user a feel of what to use when, when efficiency is a must. And if it’s not important then any garbage code will do, as we see all too often…
Paul commented :
Titus: Thanks for noticing; the passage in question has disappeared from the Python docs, so I’ve removed the link.
Momus: Welcome to the world of Python! As for the “why” – in my opinion it’s a useful semantic distinction that produces code that’s easier to read and maintain. As a bonus, as I suggest above, it also paves the way to experience with interesting functional programming languages like Haskell.
seb commented :
thanx for the prog definition
Orhan commented :
A bit confused about tuples not having an index method:
>>> ('a', 'b', 'c')[2]
'c'
>>> ['a', 'b', 'c'][2]
'c'
Preston commented :
Orhan, that is not the index method.
>>> ['a','b','c'].index('c')
2
>>> ('a','b','c').index('c')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'index'
kernelmanic commented :
Looks like someone changed their mind:
>>> ['a','b','c'].index('c')
2
>>> ('a','b','c').index('c')
2
>>>
It seems that everyone who thinks that tuples are just lists with restrictions are either not reading the comments and articles, or they are not realizing that the tuple is simply a heck of a lot of work that is done for you.
It is not a list with restrictions. It is a bunch of code that you would have to write over and over again that is rolled into the base language and given to you as a ’type’.
A tuple allows you to do things that you cant do in lists. You would be required to create your own data structures and objects and methods in order to code the kinds of things that tuples allow you to do.
For example, if you wanted to associate a bunch of textual information for a bunch of people ( say name email phone number etc - for many people ) Now lets say you wanted to access that info using a set of data points. A very silly but workable example: What if you wanted to separate people ( for marketing purposes perhaps ) based on their answer to the old chat room A/S/L question.
The would be an ever-expanding set of tuples of the form (25, ‘F’, ‘Brooklyn’) (21, ‘F’, ‘Osaka’ ) which you could easily map to date of birth i.e. (1986, ‘F’, ‘Brooklyn’) (1990, ‘F’, ‘Tokyo’) You could even add the name of the chat room in the tuple. ;) (1990, ‘F’, ‘Tokyo’, ‘#cowboybebop’ ) You could build dictionaries of names and emails and phone numbers - keyed by the tuple corresponding to their A/S/L etc. It is a silly example, but it demonstrates how powerful tuples can be.
If you wanted a to store or access names numbers and email addresses for all girls between 20 and 25 who live in Osaka and hang out in xyz chatroom, you could easily roll up a dictionary to store it. With lists it would be boring. slow, sucky and you would have to deal with irrelevant things like indexes. Or you could roll your own data structure each time. By that time, I would already have the list zapped into my mobile device…. Just sayin.
vj100 commented :
Tuples in v 3.2.2 do have an index option.
Not sure if this was available in versions prior
malpaso commented :
As @Vroo notes above it’s plain wrong and misleading to say that lists are homogeneous and tuples are heterogeneous. These two statements are completely false:
- Tuples (generally) are sequences of different kinds of stuff, and you deal with the tuple as a coherent unit.
- Lists (generally) are sequences of the same kind of stuff, and you deal with the items individually.
It’s not a subtle difference either. It’s no difference at all. You would serve your readers well if you remove it entirely because you are leading them astray.
Paul commented :
@malpaso – I think you misunderstand what I’m trying to say here. I’m not talking about a hard technical difference, I’m talking about a real difference in usage patterns.
As a test of my idea, I’d propose this: from the standard library, pick a random collection of lines that manipulate tuples or lists. Say 10 of each.
Now, are most of the tuples in accord with my statement beginning “Tuples (generally)…”? And are most of the lists in accord with my statement beginning “Lists (generally)…”?
If so, I stand by my point. If not, I’m interested.
Patrick commented :
Thank you. I am switching to python (from a background in MATLAB and Maple) and wanted you to know how much I appreciate your clear and concise explanation of the topic past the popular “lists are mutable.” You may have written this a long time ago, but it made the differences easy to see and is a very useful post.
zxq9 commented :
There is a lot of argument here, but most of it seems to be because people have grown familiar with the abuse/unthinking use of touples as a data type, not because they grok the difference. A lot of code out there has touples of touples where lists of touples make more sense, both for convenience and semantically – and perhaps this sort of example could have shed some light on others’ misunderstanding.
Using the chat room ASL example above, if I have a bunch of touples with information such as (‘32’, ‘Male’, ‘Osaka’) and (‘25’, ‘Female’, ‘Texas’) most code I see keeps track of this sort of thing by rolling it up into another touple, and sort-of appending by redeclaration via +=
people = (('25', 'Female', 'Texas'), ('32', 'Male', 'Osaka))
people += ((age, sex, location))
Which is not nearly as useful as making people be a list of touples wherein the position of each piece of data is semantically defined and important, but the order of the entries themselves do not have any meaning of its own. And, for the “why doesn’t this article discuss language implementation in detail” (despite that explicitely not being the point of a language such as Python…), it just so happens that append() and extend() are more efficient than += on a touple or a list, and considering the use case I would imagine this was intentional.
Paul commented :
Patrick – you’re welcome! Very glad to hear it was useful to you. That’s what I was going for.
zxq9 – thanks for your comment. I agree, tuples of tuples like that make little sense.
Zachary Young commented :
Thanks for the write up: it’s at least a quick intro to a concept that for me was ambigous, and I got here because I looked up a piece of code I had written 2 months ago that was returning a tuple, and asked, “why a tuple, does a list make more sense?” Either by odds (50/50) or by some other force (had seen some good code somewhere else recently) I think I made the right decision, and your article helped show me that.
Thanks again.
Paul commented :
Zachary - excellent! Glad to confirm your good instincts.
dseeking1 commented :
Glad I came across this article (and am surprised that there isn’t more on the topic in the web). I’m a telecoms engineer learning Python primarily for my own interests. I now understand how tuples and lists are intended to be used (heterogeneous vs homogeneous) and how this relates to changeability vs unchangeability (mutability vs unmutability). Thanks Paul AND all the other contributors (who clarified the key ideas).
Kumar commented :
Really great article and very nice comments from readers…. really helped a lot Thank you so much
jimmy commented :
Thanks for the explanation. I am also learning Python.
It seems that semantics and implicit programming is something that a lot of programmers aren’t taught or don’t pick up.
When I read a program, I wonder why a programmer chose a specific way of doing something based on their algorithms and data structures, especially if I understand what is supposed to be happening, but I don’t understand why.
As you stated above, understanding the semantic differences between different data types is crucial to designing appropriate algorithms. Too many programmers walk around with sledgehammers when a ball peen is all they need, or maybe, even, a rubber mallet.
So what is a Python equivalent to a C structure? I am used to s.a nomenclature to access data out of a structure. You can’t do that with a tuple and dictionaries are relatively slow.
So, to use your example, how does the time tuple map to a struct_tm?
Dobes Vandermeer commented :
Another way of looking at this is that a tuple is supposed to be a sort of “compound value” - it’s in the same group as numbers and strings.
A list, on the other hand, is a “container”, so it fits in with sets and maps.
Chirag commented :
This is 5 years old post. My curiosity to know beyond routinely known difference between these two types brought me here.
Your second example doesn’t apply to those who have migrated to python 3 because range() returns a memory efficient iterator.
Overall, your article still gives a pragmatic overview on choosing between list and tuples. Makes sense.
Matt Stevens commented :
Great post, I couldn’t understand this concept when I read a few answers on StackOverflow – as soon as you mentioned struct
, it all fell into place. Those old days messing around with C sure do come in useful :-).
Marko Knöbl commented :
Thanks for your explanations - they helped me understand the intended distinction between tuples and lists. (Even if I don’t find that distinction very useful)
However, I recently found out that even some builtin functions and classes don’t follow this convention:
>>>isinstance(42.0, (int, float))
True
>>>isinstance(42.0, [int, float])
TypeError: ...
>>>'mypic.png'.endswith(('.png', '.jpg'))
True
>>>'mypic.png'.endswith(['.png', '.jpg'])
TypeError: ...
I think that in both cases using a list as the datatype would make more sense with regard to the described convention. Is there any good reason why these functions don’t accept lists?
Marko Knöbl commented :
Oops … seems like the code I posted was not formatted as intended. Hope it works better now:
isinstance(42.0, (int, float))
True
isinstance(42.0, [int, float])
TypeError:...
'mypic.png'.endswith(('.png', '.jpg'))
True
'mypic.png'.endswith(['.png', '.jpg'])
TypeError:...
Bulwinkel commented :
Thank you for this excellent explanation!