Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need tuples in Python (or any immutable data type)?

Tags:

python

tuples

People also ask

Why do we need tuple in Python?

Tuples are used to store multiple items in a single variable. Tuple is one of 4 built-in data types in Python used to store collections of data, the other 3 are List, Set, and Dictionary, all with different qualities and usage. A tuple is a collection which is ordered and unchangeable.

Why are tuples in Python immutable?

Tuples and lists are the same in every way except two: tuples use parentheses instead of square brackets, and the items in tuples cannot be modified (but the items in lists can be modified). We often call lists mutable (meaning they can be changed) and tuples immutable (meaning they cannot be changed).

Why tuple is an immutable data type?

These tuples are an ordered collection of elements of different data types. Furthermore, we represent them by writing the elements inside the parenthesis separated by commas. We can also define tuples as lists that we cannot change. Therefore, we can call them immutable tuples.

Why do we need immutable data type?

Its State cannot be changed whatsoever, It tends to represent a constant value once initialized. Examples – integer, complex, string, float, Tuple, Complex, Frozen set. Therefore if any variable has initialized a value corresponding to any of these immutable data types, one cannot change it ever.


  1. immutable objects can allow substantial optimization; this is presumably why strings are also immutable in Java, developed quite separately but about the same time as Python, and just about everything is immutable in truly-functional languages.

  2. in Python in particular, only immutables can be hashable (and, therefore, members of sets, or keys in dictionaries). Again, this afford optimization, but far more than just "substantial" (designing decent hash tables storing completely mutable objects is a nightmare -- either you take copies of everything as soon as you hash it, or the nightmare of checking whether the object's hash has changed since you last took a reference to it rears its ugly head).

Example of optimization issue:

$ python -mtimeit '["fee", "fie", "fo", "fum"]'
1000000 loops, best of 3: 0.432 usec per loop
$ python -mtimeit '("fee", "fie", "fo", "fum")'
10000000 loops, best of 3: 0.0563 usec per loop

None of the answers above point out the real issue of tuples vs lists, which many new to Python seem to not fully understand.

Tuples and lists serve different purposes. Lists store homogenous data. You can and should have a list like this:

["Bob", "Joe", "John", "Sam"]

The reason that is a correct use of lists is because those are all homogenous types of data, specifically, people's names. But take a list like this:

["Billy", "Bob", "Joe", 42]

That list is one person's full name, and their age. That isn't one type of data. The correct way to store that information is either in a tuple, or in an object. Lets say we have a few :

[("Billy", "Bob", "Joe", 42), ("Robert", "", "Smith", 31)]

The immutability and mutability of Tuples and Lists is not the main difference. A list is a list of the same kind of items: files, names, objects. Tuples are a grouping of different types of objects. They have different uses, and many Python coders abuse lists for what tuples are meant for.

Please don't.


Edit:

I think this blog post explains why I think this better than I did:

  • Understanding tuples vs. lists in Python - E-Scribe

if I must convert a tuple to a set or list to be able to sort them, what's the point of using a tuple in the first place?

In this particular case, there probably isn't a point. This is a non-issue, because this isn't one of the cases where you'd consider using a tuple.

As you point out, tuples are immutable. The reasons for having immutable types apply to tuples:

  • copy efficiency: rather than copying an immutable object, you can alias it (bind a variable to a reference)
  • comparison efficiency: when you're using copy-by-reference, you can compare two variables by comparing location, rather than content
  • interning: you need to store at most one copy of any immutable value
  • there's no need to synchronize access to immutable objects in concurrent code
  • const correctness: some values shouldn't be allowed to change. This (to me) is the main reason for immutable types.

Note that a particular Python implementation may not make use of all of the above features.

Dictionary keys must be immutable, otherwise changing the properties of a key-object can invalidate invariants of the underlying data structure. Tuples can thus potentially be used as keys. This is a consequence of const correctness.

See also "Introducing tuples", from Dive Into Python.


Sometimes we like to use objects as dictionary keys

For what it's worth, tuples recently (2.6+) grew index() and count() methods


I've always found having two completely separate types for the same basic data structure (arrays) to be an awkward design, but not a real problem in practice. (Every language has its warts, Python included, but this isn't an important one.)

Why does anyone care if a variable lives at a different place in memory than when it was originally allocated? This whole business of immutability in Python seems to be over emphasized.

These are different things. Mutability isn't related to the place it's stored in memory; it means the stuff it points to can't change.

Python objects can't change location after they're created, mutable or not. (More accurately, the value of id() can't change--same thing, in practice.) The internal storage of mutable objects can change, but that's a hidden implementation detail.

>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167

This isn't modifying ("mutating") the variable; it's creating a new variable with the same name, and discarding the old one. Compare to a mutating operation:

>>> a = [1,2,3]
>>> id(a)
3084599212L
>>> a[1] = 5
>>> a
[1, 5, 3]
>>> id(a)
3084599212L

As others have pointed out, this allows using arrays as keys to dictionaries, and other data structures that need immutability.

Note that keys for dictionaries do not have to be completely immutable. Only the part of it used as a key needs to be immutable; for some uses, this is an important distinction. For example, you could have a class representing a user, which compares equality and a hash by the unique username. You could then hang other mutable data on the class--"user is logged in", etc. Since this doesn't affect equality or the hash, it's possible and perfectly valid to use this as a key in a dictionary. This isn't too commonly needed in Python; I just point it out since several people have claimed that keys need to be "immutable", which is only partially correct. I've used this many times with C++ maps and sets, though.


As gnibbler offered in a comment, Guido had an opinion that is not fully accepted/appreciated: “lists are for homogeneous data, tuples are for heterogeneous data”. Of course, many of the opposers interpreted this as meaning that all elements of a list should be of the same type.

I like to see it differently, not unlike others also have in the past:

blue= 0, 0, 255
alist= ["red", "green", blue]

Note that I consider alist to be homogeneous, even if type(alist[1]) != type(alist[2]).

If I can change the order of the elements and I won't have issues in my code (apart from assumptions, e.g. “it should be sorted”), then a list should be used. If not (like in the tuple blue above), then I should use a tuple.


They are important since they guarantee the caller that the object they pass won't be mutated. If you do this:

a = [1,1,1]
doWork(a)

The caller has no guarantee of the value of a after the call. However,

a = (1,1,1)
doWorK(a)

Now you as the caller or as a reader of this code know that a is the same. You could always for this scenario make a copy of the list and pass that but now you are wasting cycles instead of using a language construct that makes more semantic sense.