Reputation: 1413
I have just read an article: The 10 Most Common Mistakes That Python Developers Make. The problem #1 still puzzled me a lot. I will describe my problem with the codes below.
>>>def foo(bar=[]):
... bar.append("baz")
... return bar
>>> foo()
["baz"]
>>> foo()
["baz", "baz"]
It not works, the answer in the article says list is an multable type and the default value changes during the call.But when I try this one
def foo(bar=[]):
if bar == []:bar=[]
...
it works, so what makes the difference?
Upvotes: 1
Views: 123
Reputation: 17263
In your code you assign a new list to bar
instead using the default argument. Now if you modify the new list the changes of course aren't shown in the default argument which is different object.
The typical solution is to assign None
to the default argument and explicitly check it at the beginning of function:
def foo(bar=None):
if bar is None:
bar = []
Note that although it looks a lot like your version there are differences:
def foo(bar=[]):
if bar == []:
bar = []
bar.append(1)
def foo2(bar=None):
if bar is None:
bar = []
bar.append(1)
l = []
foo(l)
print l # []
l = []
foo2(l)
print l # [1]
Upvotes: 0
Reputation: 6597
Default arguments are created at function definition in Python. This means that when you provide a list as a default argument, that list will persist for all function calls in which that argument is not explicitly passed. In the second example, you are reassigning the argument to a different value. That creates a new list and will fix the problem. A more common solution to this "bug"/"feature" is to assign the default argument a value of None
and then check it at the top of the function. That would look something like this:
def foo(bar=None):
if bar is None:
bar = []
However, the code that you wrote in the second example achieves the same effect.
Upvotes: 4