Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the "mutable default argument fix" syntax is so ugly, asks python newbie

Now following my series of "python newbie questions" and based on another question.

Prerogative

Go to http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables and scroll down to "Default Parameter Values". There you can find the following:

def bad_append(new_item, a_list=[]):     a_list.append(new_item)     return a_list  def good_append(new_item, a_list=None):     if a_list is None:         a_list = []     a_list.append(new_item)     return a_list 

There's even an "Important warning" on python.org with this very same example, tho not really saying it's "better".

One way to put it

So, question here is: why is the "good" syntax over a known issue ugly like that in a programming language that promotes "elegant syntax" and "easy-to-use"?

edit:

Another way to put it

I'm not asking why or how it happens (thanks Mark for the link).

I'm asking why there's no simpler alternative built-in the language.

I think a better way would probably being able to do something in the def itself, in which the name argument would be attached to a "local", or "new" within the def, mutable object. Something like:

def better_append(new_item, a_list=immutable([])):     a_list.append(new_item)     return a_list 

I'm sure someone can come with a better syntax, but I'm also guessing there must be a very good explanation to why this hasn't been done.

like image 265
cregox Avatar asked Apr 14 '10 18:04

cregox


People also ask

What is a mutable default argument in Python?

In Python, when passing a mutable value as a default argument in a function, the default argument is mutated anytime that value is mutated. Here, "mutable value" refers to anything such as a list, a dictionnary or even a class instance.

What are default arguments in Python Why is the concept of default arguments useful?

Python has a different way of representing syntax and default values for function arguments. Default values indicate that the function argument will take that value if no argument value is passed during the function call. The default value is assigned by using the assignment(=) operator of the form keywordname=value.

What is the use of default arguments explain with the help of an example?

Default arguments are overwritten when the calling function provides values for them. For example, calling the function sum(10, 15, 25, 30) overwrites the values of z and w to 25 and 30 respectively.


2 Answers

This is called the 'mutable defaults trap'. See: http://www.ferg.org/projects/python_gotchas.html#contents_item_6

Basically, a_list is initialized when the program is first interpreted, not each time you call the function (as you might expect from other languages). So you're not getting a new list each time you call the function, but you're reusing the same one.

I guess the answer to the question is that if you want to append something to a list, just do it, don't create a function to do it.

This:

>>> my_list = [] >>> my_list.append(1) 

Is clearer and easier to read than:

>>> my_list = my_append(1) 

In the practical case, if you needed this sort of behavior, you would probably create your own class which has methods to manage it's internal list.

like image 154
Seth Avatar answered Sep 18 '22 13:09

Seth


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.

like image 24
Mike Graham Avatar answered Sep 22 '22 13:09

Mike Graham