views:

1769

answers:

6

Is there any performance difference between tuples and lists when it comes to instantiation and retrieval of elements?

A: 

Tuples should be slightly more efficient and because of that, faster, than lists because they are immutable.

ctcherry
Why do you say that immutability, in and of itself, increases efficiency? Especially efficiency of instantiation and retrieval?
Blair Conrad
It seems Mark's reply above mine has covered the disassembled instructions of what happens inside of Python. You can see that instantiation takes fewer instructions, however in this case, retrieval is apparently identical.
ctcherry
+25  A: 

In general, you might expect tuples to be slightly faster. However you should definitely test your specific case (if the difference might impact the performance of your program -- remember "premature optimization is the root of all evil").

Python makes this very easy: timeit is your friend.

$ python -m timeit "x=(1,2,3,4,5,6,7,8)"
10000000 loops, best of 3: 0.0388 usec per loop

$ python -m timeit "x=[1,2,3,4,5,6,7,8]"
1000000 loops, best of 3: 0.363 usec per loop

and...

$ python -m timeit -s "x=(1,2,3,4,5,6,7,8)" "y=x[3]"
10000000 loops, best of 3: 0.0938 usec per loop

$ python -m timeit -s "x=[1,2,3,4,5,6,7,8]" "y=x[3]"
10000000 loops, best of 3: 0.0649 usec per loop

So in this case, instantiation is almost an order of magnitude faster for the tuple, but item access is actually somewhat faster for the list! So if you're creating a few tuples and accessing them many many times, it may actually be faster to use lists instead.

Of course if you want to change an item, the list will definitely be faster since you'd need to create an entire new tuple to change one item of it (since tuples are immutable).

dF
man, thanks for telling me about timeit!
Stefan Monov
+22  A: 

The "dis" module disassembles the byte code for a function and is useful to see the difference between tuples and lists.

In this case, you can see that accessing an element generates identical code, but that assigning a tuple is much faster than assigning a list.

>>> def a():
...     x=[1,2,3,4,5]
...     y=x[2]
...
>>> def b():
...     x=(1,2,3,4,5)
...     y=x[2]
...
>>> import dis
>>> dis.dis(a)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 LOAD_CONST               4 (4)
             12 LOAD_CONST               5 (5)
             15 BUILD_LIST               5
             18 STORE_FAST               0 (x)

  3          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               2 (2)
             27 BINARY_SUBSCR
             28 STORE_FAST               1 (y)
             31 LOAD_CONST               0 (None)
             34 RETURN_VALUE
>>> dis.dis(b)
  2           0 LOAD_CONST               6 ((1, 2, 3, 4, 5))
              3 STORE_FAST               0 (x)

  3           6 LOAD_FAST                0 (x)
              9 LOAD_CONST               2 (2)
             12 BINARY_SUBSCR
             13 STORE_FAST               1 (y)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE
Mark Harrison
Err, just that the same bytecode is generated absolutely does not mean the same operations happen at the C (and therefore cpu) level. Try creating a class `ListLike` with a `__getitem__` that does something horribly slow, then disassemble `x = ListLike((1, 2, 3, 4, 5)); y = x[2]`. The bytecode will be more like the tuple example above than the list example, but do you really believe that means performance will be similar?
mzz
It seems you're saying that that some types are more efficient than others. That makes sense, but the overhead of list and tuple generations seems to be orthogonal to the data type involved, with the caveat that they are lists and tuples of the same data type.
Mark Harrison
+2  A: 

Tuples, being immutable, are more memory efficient; lists, for efficiency, overallocate memory in order to allow appends without constant reallocs. So, if you want to iterate through a constant sequence of values in your code (eg for direction in 'up', 'right', 'down', 'left':), tuples are preferred, since such tuples are pre-calculated in compile time.

Access speeds should be the same (they are both stored as contiguous arrays in the memory).

But, alist.append(item) is much preferred to atuple+= (item,) when you deal with mutable data. Remember, tuples are intended to be treated as records without field names.

ΤΖΩΤΖΙΟΥ
A: 

You should also consider the array module in the standard library if all the items in your list or tuple are of the same type. It can be faster and take less memory.

It'll take less memory, but access time will probably be a bit slower, rather than faster. Accessing an element requires the packed value to be unboxed to a real integer, which will slow the process down.
Brian
A: 

Structures are not efficient. Operations are efficient. Ask better questions that actually make sense.

ironfroggy