In Python I can append values to a list using the append() function among other things, but with tuples this all changes and the way they are handled is different. Its structure seems very similar to that of a list, and I would like to know its usefulness or purpose.
Tuples in Python have this structure:
a = (1,2,3,4)
While the lists is another:
b = [1,2,3,4]
I would be grateful if someone could explain to me why tuples are necessary in Python and in what cases they should be used.
The main difference is that tuples are immutable (they cannot be modified) and lists are not. This immutability makes it possible to apply a hash function to it.
Another very important issue is that tuples are more efficient than lists . So unless you need mutability in your data structure, it's more convenient to use a tuple instead of a list. Let's see why in detail.
1. Compilation
Python recognizes and evaluates tuples as constant expressions at compile time, rather than at execution, this is known as Constant Folding .
disassembly
I can demonstrate this to you with the python moduleDeparture
Effectively, Python has evaluated the tuple as a constant expression and returned it, however in the list, it has had to evaluate each element of the list as a constant, then build the list and finally return it. This of course has a cost of time let's see
Departure:
A tuple is about 10 times faster
Caveat
This behavior happens because we have created the tuple with immutable elements, if only one of the elements were mutable , the tuple would be evaluated by Python in the same way as the list and the times would be similar.
2. Copy
When you want to copy a list, Python allocates memory again to create a new list. In the case of tuples, due to their immutability, they are not copied, just a shallow copy reference is created . Let's prove it:
Departure:
When copying the list they are in different memory locations , however the tuple is in the same memory location.
This also has an impact on execution times :
Departure
Note that I have copied the list from a tuple , to avoid including the extra creation time that a list has (what we saw in point 1) and so that we focus exclusively on the copy and it is a fair comparison .
3. Storage
The storage for a tuple is exact, that is, Python reserves the space just and necessary to store a tuple, since it is immutable. In lists it is different, Python reserves more space than necessary for a list, which is known as Overallocation and pre-allocate with the aim of optimizing the entry of elements in said list. If you want to know more, you can see Dynamic array . Let's see this:
Departure:
Indeed, the tuple always reserves 8 bytes and occupies just enough space for the elements, however the list occupies more space and makes different memory reservations.
This is because, when reserving more memory than necessary, Python uses an algorithm that, looking at the size of the list, calculates how much more space it is going to reserve. Thus if, for example, we use
.append()
and the list grows, we avoid having to re-reserve space to enter the element, since said space is previously reserved.Bonuses
Another issue that is associated, but that can be overlooked, is that since it is immutable, the order is maintained, that is, in tuples , the order in which the elements come has meaning.
The only difference is that tuples are immutable and lists are not.
This distinction may be important for two reasons:
You may want to have a "group" of values to pass as a parameter to a function, but you want to be sure that the function will not modify any of the values in the group. Since in python everything is references, once the function receives the reference to the "group" (a list, an object) it can change its values. The only way around it is to make that group a tuple. In fact I suggest you also look into the ones
namedtuples
that are a mechanism to create something that looks like an object (with its named fields) but is actually implemented internally as a tuple, so that it is immutable.This use case is more important than it seems at first glance. I have gone crazy debugging code in which, in the end, the bug was caused because a data list did not have the data that I had loaded into it but others, because one of the multiple functions that received it as a parameter modified it. In the end I solved it by changing all my lists to tuples and seeing where the program broke when a function tried to modify the data.
Thanks to the tuples and
namedtuples
I was able to refactor the program so that all the functions are pure (they do not cause secondary effects on variables that do not belong to the function). This is much easier to debug and maintain.Almost more importantly, being immutable they are also hashable . That is, the function can be applied to them
hash()
and the result will always be the same. In a list obviously the hash could change if the elements of the list have changed.Hashing data is important because only hashing data can be stored in a set (
set()
) or can be used as dictionary keys (because these data structures are basically hash tables).So if you find yourself needing to use a list as a key in a dictionary, you'll find that you can't. Convert it to a tuple and you're good to go.
ACCORDING to resourcespython.com .
A list is not the same as a tuple, both are an ordered set of values, where the latter can be any object: a number, a string, a function, a class, an instance, etc.
The difference is that lists have a series of additional functions that allow extensive handling of the values they contain. Based on this definition, it can be said that lists are dynamic, while tuples are static.