Chapter 22, Basic
Mutability and identity
This is the chapter that separates those who memorized the syntax from those who understand the object model of Python. Almost every strange bug with lists and functions originates here.
Code for this chapter: basico/cap22_mutabilidade.py
Names, objects, and id
Remember the label from the first chapter? Each object has an identity (the id), and two names can point to the same object. The operator == compares values. The operator is compares identities:
a = [1, 2]
b = [1, 2]
c = a
print(a == b, a is b, a is c)
print(id(a) == id(c))
True False True
True
a and b have the same content, but are different objects. c is just another name for a.
Mutable and immutable
| Immutable (the object never changes) | Mutable (the object can change) |
|---|---|
int, float, bool, complex | list |
str, bytes | dict |
tuple, frozenset | set, bytearray |
None | Most of the objects you define |
When you "change" an immutable, you actually create a new object and point the name to it. When you change a mutable, the object changes, and all names pointing to it see the change.
What happens in functions
Python passes the name of the object, not a copy. If the function alters the object, the caller sees it. If the function only points the local name to another object, the caller does not see it:
def anexar(lista):
lista.append(99)
def reatribuir(lista):
lista = [0]
dados = [1, 2]
anexar(dados)
print(dados)
reatribuir(dados)
print(dados)
[1, 2, 99]
[1, 2, 99]
The array trap
Multiplying a list by a number repeats the reference, not the object. That's why the "matrix" below has three rows that are, in fact, the same list:
errada = [[0] * 3] * 3
errada[0][0] = 1
print(errada)
certa = [[0] * 3 for _ in range(3)]
certa[0][0] = 1
print(certa)
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
The second form uses a list comprehension, which I present at the intermediate level. It creates a new list on each iteration.
When to use is
Use
iswithNone,TrueandFalseand with sentinel values that you created yourself. For everything else, use==. Comparing numbers or strings withismay work by chance, due to optimizations of the interpreter, and break at another time.
Exercise 1
Copy a truth matrix
Write copiar_matriz(matriz) so that altering the copy does not change the original.