Can tuples be replaced with lists all the time?

S

Sam

My understanding of Python tuples is that they are like immutable lists. If this is the cause, why can't we replace tuples with lists all the time (just don't reassign the lists)? Correct me if I am wrong.
 
C

Chris Angelico

My understanding of Python tuples is that they are like immutable lists. If this is the cause, why can't we replace tuples with lists all the time (just don't reassign the lists)? Correct me if I am wrong.

One reason is performance/efficiency. If Python knows this is never
going to change, it can save some effort. But a more important reason
is hashability.
mapping = {}
key = (1,2)
mapping[key] = "Hello"
key = (1,3)
mapping[key] = "World"
key = (2,3)
mapping[key] = "!"
mapping
{(1, 2): 'Hello', (1, 3): 'World', (2, 3): '!'}

You can't do this with lists:
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
mapping[key]
TypeError: unhashable type: 'list'

This is because any two tuples are either equal or not equal, they
can't be otherwise. I can create another tuple and look up something
in the above mapping:
'World'

But with lists, their equality can change.
lst1 = [1,2]
lst2 = [1,3]
lst1 == lst2 False
lst1[1] += 1
lst1 == lst2 True
lst1[1] += 1
lst1 == lst2
False

So it would be very difficult and dangerous to try to use a list as a
dictionary key. The only safe way to do it is by identity, and that's
only useful in a very small set of situations. So Python happily
declares that a tuple can be a dict key and a list can't, and that's
now a key (if you'll excuse the pun) difference between them.

ChrisA
 
P

Paul Rubin

Sam said:
My understanding of Python tuples is that they are like immutable
lists. If this is the cause, why can't we replace tuples with lists
all the time (just don't reassign the lists)?

You can do that a lot of the time but not always. For example, you can
use a tuple as a dictionary key, but not a list, since keys are supposed
to be immutable.
 
8

88888 Dihedral

My understanding of Python tuples is that they are like immutable lists. If this is the cause, why can't we replace tuples with lists all the time (just don't reassign the lists)? Correct me if I am wrong.
======

OK, lets be serious about high-level
programming lnguages.

Python is a dynamical typed
( name binding mechnism implicitly),
imperative language with the built in auto GC and the heap plus stack
managements in the bundled scriptor.

A tuple is treated immutable and
a list is mutable in Python.

I suggest one can read
the introductions about Erlang
which is a non-imperative high
level language in the 5 to 6 th gen
programming languages in back-end
server applictions for the robustness
and maintainence costs.

Neverthless, Python is regarded as a programming firendly language
when comparing with other high level
languages.
 
M

Mark Lawrence

Grant Edwards said:
In constrast, tuples are often used as fixed-length heterogenous
containers (more like a struct in C except the fields are named 0, 1,
2, 3, etc.). In a particular context, the Nth element of a tuple will
always mean one thing (e.g. a person's last name) while the Mth
element will always be something else (e.g. a person's age).

And, of course, namedtuples make that much more explicit.

It also appears that tuples are more memory efficient. I just ran some
quick tests on my OSX box. Creating a list of 10 million [1, 2, 3, 4,
5] lists gave me a 1445 MB process. The name number of (1, 2, 3, 4, 5)
tuples was 748 MB. I'm sure this is implementation dependent, but it
seems plausible to assume similar results will be had on other
implementations.

In CPython a list is overallocated so there's usually spare slots
available if you want to add something to it. In contrast you know when
you create the tuple just how big it is so no overallocation is needed.
 
T

Terry Reedy

On 23/02/2014 17:48, Roy Smith wrote:
It also appears that tuples are more memory efficient. I just ran some
quick tests on my OSX box. Creating a list of 10 million [1, 2, 3, 4,
5] lists gave me a 1445 MB process. The name number of (1, 2, 3, 4, 5)
tuples was 748 MB. I'm sure this is implementation dependent, but it
seems plausible to assume similar results will be had on other
implementations.

The numbers sound right.
In CPython a list is overallocated so there's usually spare slots
available if you want to add something to it. In contrast you know when
you create the tuple just how big it is so no overallocation is needed.

Besides which, in CPython, a tuple is one block of memory, with a
PyObject header followed by the object references, while a list uses 2
blocks of memory. The first has a PyObject header, followed by a
reference to the list block, its allocated length (minimum 8 I believe),
and its current in-use length. The over-allocated list block, which must
also start on a 4 or 8 byte alignment boundary, has the object
references plus extra space.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,078
Messages
2,570,570
Members
47,204
Latest member
MalorieSte

Latest Threads

Top