Now following my series of \"python newbie questions\" and based on another question.
Go to http://python.net/~goodger/projects/pyco
Default arguments are evaluated at the time the def
statement is executed, which is the probably the most reasonable approach: it is often what is wanted. If it wasn't the case, it could cause confusing results when the environment changes a little.
Differentiating with a magic local
method or something like that is far from ideal. Python tries to make things pretty plain and there is no obvious, clear replacement for the current boilerplate that doesn't resort to messing with the rather consistent semantics Python currently has.
I've edited this answer to include thoughts from the many comments posted in the question.
The example you give is flawed. It modifies the list that you pass it as a side effect. If that's how you intended the function to work, it wouldn't make sense to have a default argument. Nor would it make sense to return the updated list. Without a default argument, the problem goes away.
If the intent was to return a new list, you need to make a copy of the input list. Python prefers that things be explicit, so it's up to you to make the copy.
def better_append(new_item, a_list=[]):
new_list = list(a_list)
new_list.append(new_item)
return new_list
For something a little different, you can make a generator that can take a list or a generator as input:
def generator_append(new_item, a_list=[]):
for x in a_list:
yield x
yield new_item
I think you're under the misconception that Python treats mutable and immutable default arguments differently; that's simply not true. Rather, the immutability of the argument makes you change your code in a subtle way to do the right thing automatically. Take your example and make it apply to a string rather than a list:
def string_append(new_item, a_string=''):
a_string = a_string + new_item
return a_string
This code doesn't change the passed string - it can't, because strings are immutable. It creates a new string, and assigns a_string to that new string. The default argument can be used over and over again because it doesn't change, you made a copy of it at the start.