views:

444

answers:

6

In Python, when should you use lists and when tuples?

Sometimes you don't have a choice, for example if you have

"hello %s you are %s years old" % x

then x must be a tuple.

But if I am the one who designs the API and gets to choose the data types, then what are the guidelines?

+18  A: 

I believe (and I am hardly well-versed in Python) that the main difference is that a tuple is immutable (it can't be changed in place after assignment) and a list is mutable (you can append, change, subtract, etc).

So, I tend to make my tuples things that shouldn't change after assignment and my lists things that can.

thornomad
+3  A: 

Tuples are fixed size in nature whereas Lists are dynamic. Consult this for more details.

  1. You can't add elements to a tuple. Tuples have no append or extend method.
  2. You can't remove elements from a tuple. Tuples have no remove or pop method.
  3. You can't find elements in a tuple. Tuples have no index method.
  4. You can, however, use in to see if an element exists in the tuple.

In other words, a tuple is immutable whereas a list is mutable.

Tuples are faster than lists. If you're defining a constant set of values and all you're ever going to do with it is iterate through it, use a tuple instead of a list.

It makes your code safer if you “write-protect” data that does not need to be changed. Using a tuple instead of a list is like having an implied assert statement that this data is constant, and that special thought (and a specific function) is required to override that.

Consult this for more details.

jldupont
The "write-protect" analogy only goes so far: the membership of a tuple cannot be changed *but* mutable elements of a tuple *can* be changed: l = list(); t = (l, l); l.append(1)
Ned Deily
Using a tuple over a list for speed is a really silly optimization.
Mike Graham
@mike: how's that?
jldupont
+3  A: 

Must it be mutable? Use a list. Must it not be mutable? Use a tuple.

Otherwise, it's a question of choice.

For collections of heterogeneous objects (like a address broken into name, street, city, state and zip) I prefer to use a tuple. They can always be easily promoted to named tuples.

Likewise, if the collection is going to be iterated over, I prefer a list. If it's just a container to hold multiple objects as one, I prefer a tuple.

AFoglia
+1 for the link to named tuples.
Rod Hyde
+10  A: 

There's also a strong culture of tuples being for heterogenous collections, similar to what you'd use structs for in C, and lists being for homogenous collections, similar to what you'd use arrays for. But I've never quite squared this with the mutability issue mentioned in the other answers. Mutability has teeth to it (you actually can't change a tuple), while homogeneity is not enforced, and so seems to be a much less interesting distinction.

Ned Batchelder
I use this as the deciding factor usually.
FogleBird
I like this one, as it provides a higher level rationale
flybywire
+4  A: 

The first thing you need to decide is whether the data structure needs to be mutable or not. As has been mentioned, lists are mutable, tuples are not. This also means that tuples can be used for dictionary keys, wheres lists cannot.

In my experience, tuples are generally used where order and position is meaningful and consistant. For example, in creating a data structure for a choose your own adventure game, I chose to use tuples instead of lists because the position in the tuple was meaningful. Here is one example from that data structure:

pages = {'foyer': {'text' : "some text", 
          'choices' : [('open the door', 'rainbow'),
                     ('go left into the kitchen', 'bottomless pit'),
                     ('stay put','foyer2')]},}

The first position in the tuple is the choice displayed to the user when they play the game and the second position is the key of the page that choice goes to and this is consistent for all pages.

Tuples are also more memory efficient than lists, though I'm not sure when that benefit becomes apparent.

Also check out the chapters on lists and tuples in Think Python.

Amanda Nyren
A: 

But if I am the one who designs the API and gets to choose the data types, then what are the guidelines?

For input parameters it's best to accept the most generic interface that does what you need. It is seldom just a tuple or list - more often it's sequence, sliceable or even iterable. Python's duck typing usually gets it for free, unless you explicitly check input types. Don't do that unless absolutely unavoidable.

For the data that you produce (output parameters) just return what's most convenient for you, e.g. return whatever datatype you keep or whatever your helper function returns.

One thing to keep in mind is to avoid returning a list (or any other mutable) that's part of your state, e.g.

class ThingsKeeper
    def __init__(self):
        self.__things = []

    def things(self):
        return self.__things  #outside objects can now modify your state

    def safer(self):
        return self.__things[:]  #it's copy-on-write, shouldn't hurt performance
Rafał Dowgird