Javier's response is very good but only solves your specific case, maybe what you really want to know is that the lists work by reference .
What this means is that if you create a list l1
:
>>> l1 = []
Actually what you are doing is passing a reference to the object. Therefore if you then create another list based on the first one:
>>> l2 = l1
Now l2
has the reference to the same object. To understand it better, consider the following example:
>>> l1 = [1, 2, 3]
>>> l2 = l1
>>> l2.append(4)
>>> l1
[1, 2, 3, 4]
>>> l2
[1, 2, 3, 4]
>>> l1 is l2 # Tienen referencia al mismo objeto
True
As you can see, adding an element to l2
also happens the same for l1
since both variables have the reference to the same list.
The same thing happens with dictionaries:
>>> d1 = {'nombre': 'Cesar'}
>>> d2 = d1
>>> d2['apellido'] = 'Bustios'
>>> d1
{'apellido': 'Bustios', 'nombre': 'Cesar'}
>>> d2
{'apellido': 'Bustios', 'nombre': 'Cesar'}
>>> d1 is d2 # Tienen referencia al mismo objeto
True
What happens when executing your script, is that in the definition of your function arguments_mutables
, you are creating in arg1
the reference to a list, that is why the successive calls to this function increases the size of the list since in fact the reference to the same object is being used.
If you want to keep the original object when applying an operation, what you have to do is pass it a copy of the object. In the case of lists this is very simple:
>>> l1 = [1, 2, 3, 4, 5]
>>> l2 = l1[:] # Una copia, un objeto nuevo
>>> l2.extend([6, 7, 8, 9, 10])
>>> l1
[1, 2, 3, 4, 5]
>>> l2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> l1 is l2 # No tienen referencia al mismo objeto
False
In the case of dictionaries, you can use the copy
method:
>>> d1 = {'nombre': 'Cesar'}
>>> d2 = d1.copy() # Una copia, un objeto nuevo
>>> d2['apellido'] = 'Bustios'
>>> d1
{'nombre': 'Cesar'}
>>> d2
{'apellido': 'Bustios', 'nombre': 'Cesar'}
>>> d1 is d2 # No tienen referencia al mismo objeto
False
For more complex dictionaries you should use copy.deepcopy
.
If you have a function, you can also copy it to keep the original object. Consider the following function:
import random
def extendedora(lista):
lista.append(random.randint(6, 10))
return lista
Now, the first case, using the same list:
>>> lista_original = [1, 2, 3, 4, 5]
>>> lista_extendida = extendedora(lista_original)
>>> lista_original
[1, 2, 3, 4, 5, 9]
>>> lista_extendida
[1, 2, 3, 4, 5, 9]
>>> lista_original is lista_extendida
True
Using a copy to maintain the original list:
>>> lista_original = [1, 2, 3, 4, 5]
>>> lista_extendida = extendedora(lista_original[:])
>>> lista_original
[1, 2, 3, 4, 5]
>>> lista_extendida
[1, 2, 3, 4, 5, 6]
>>> lista_original is lista_extendida
False