views:

147

answers:

3

Which is more efficient? What is the typical use of each?

+3  A: 

Lists are mutable (can be changed), tuples are immutable. Typical use: it sounds rather trite but you use lists when you need to change the values. Tuples are generally a little more efficient because of their immutability (unless you are using them like lists and duplicating them a lot...)

Bryan Oakley
+5  A: 

A list is mutable, you can add elements to it. A tuple isn't, which means it's (slightly) more efficient. Tuples are also hashable, so can be used as e.g. the key in a dictionary.

Read this.

katrielalex
The link totally ignores set (and other, less commonly used collections which are basically variations of the others - frozenset is an immutable set, bytes it a list (with a bit of syntactical sugar), etc...). Still +1
delnan
`set` wasn't mentioned in the question, so why should be mentioned in the answer? Yes, `set` and `frozenset` have comparable differences between `list` and `tuple`. While I don't use `set`s nearly as frequently I do `list`s and `tuple`s, they are an invaluable tool in my toolbox.
Nathan Ernst
I'm nit-picking, but immutability doesn't imply hashability, any more than being mutable implies that something isn't hashable. For example instances of user defined classes are hashable by default, but this doesn't mean that they are immutable. Admittedly it would be unusual for an immutable type not to be hashable, but it certainly is possible.
Scott Griffiths
Ah, thanks for setting me straight.
katrielalex
+6  A: 

Lists are mutable sequences, with lots and lots of methods (both mutating and non-mutating ones), that are most often used as general purpose containers (their items can be objects of any types at all, although it's sometimes considered better style for lists to have items that are of the same type or types to be used equivalently).

Tuples are immutable sequences, with very few methods (all non-mutating special ones), that are most often used when you need immutability for the purpose of using a container as an item in a set or a key in a dict (though the items will also have to be immutables -- e.g. strings, numbers, or other nested tuples, for this to work). Their items can be objects of any types at all and it's perfectly normal for tuples to have items of many different and distinct types.

There are a few cases in which either a tuple or a list would serve just as well, and in such few cases the fact that tuples are a bit smaller and faster to build can be used to sway the decision in favor of tuples. For example, when a function needs to return multiple results, it's most normal to use

return fee, fie, foo, fum

i.e., return a tuple with the four items in question, rather than

return [fee, fie, foo, fum]

i.e., return a list with the four items -- besides (small gains in) performance, the "return a tuple" common idiom also deals with the issue that often the multiple results being returned are not of the same nor interchangeable types, so, stylistically speaking, using a list might be considered a more dubious choice anyway.

A useful variant of tuple is its sub-type collections.namedtuple (requires Python 2.6 or better) which lets you access items by name (with attribute syntax) as well as by index (the normal way). For example, with an import collections at the top of the module, the above return statement might become...

freturn = collections.namedtuple('freturn', 'fee fie foo fum')

def f():
  ...
return freturn(fee, fie, foo, fum)

Now, the caller of f() could use its return value as a tuple, just as before, but would gain nice alternatives such as...:

r = f()
print r.fie

in lieu of the less immediately clear and readable

print r[1]

It's important to note that a named tuple subclass made with collections.namedtuple has essentially no extra overhead compared with using a tuple directly, or, as the docs put it,

they are lightweight and require no more memory than regular tuples.

Alex Martelli
I think the docs must gloss over that, ammatorized across many instances of the named tuple, there is no additional overhead, but there is certain extra memory being used, because you're effectively dynamically creating a new type (which, of course has some, albeit slight, memory footprint). (Still got a +1, BTW, for a very thorough answer).
Nathan Ernst