I am trying to define the following function with Python,
def caja(cosas=[]):
cosas.append("lapiz")
cosas.append("martillo")
cosas.append("azulejos")
return cosas
>>> caja()
["lapiz", "martillo", "azulejos"]
Here comes the problem, when I call the function caja()
again instead of creating an empty list, it adds the data to the existing list.
>>> caja()
["lapiz", "martillo", "azulejos","lapiz", "martillo", "azulejos"]
Does anyone know how Python works in this aspect? The arguments are only evaluated once at the time of declaring the function?
Thank you
Your question is a fairly recurring topic for all of us who started in Python coming from another language. Let's go first with the solution: the correct way to do what you have in mind is like this:
Now, what is the explanation for this apparently "unnatural" behavior?
To begin with, this behavior occurs only with "mutable" default values, in your case, a list is, with strings this does not happen.
In Python, a function is just another object, so when you actually define it, you're creating a new object. The default values function in some way as the function object's own data. Let's see what happens from
def
and in subsequent invocations:When defining the function:
caja
within the module's namespacelista_valor_default
The first time we run the function:
cosas
to the objectlista_valor_default
that was defined when the function was created, the first time the behavior will be as expected, we add data, but not tocosas
(reference) but to the objectlista_valor_default
The following call with no parameters:
lista_valor_default
now it's not an empty list anymore so it willcosas
point to a list with the elements from the previous call, and we'll keep adding more elements tolista_valor_default
.Demonstration:
The following code serves to understand the commented behavior:
We see that at all times the
id
oflista
(default value) is the same as the internal variablefalsanuevalista
, so it is shown that theyappend
act on the default list.There are several alternatives, the one I mentioned above is usually the most appropriate, but eventually you could leave your function as it is defined, but the trick would be to force a copy of the default list to a new internal variable and return it, for example like this:
For more information, I recommend this article .
This is a solution:
As a parameter you were initializing a variable, that's why it was not emptied