
There are a few problems here. Deep copy of the originally created default argument can be expensive and would not work in any useful way with non-literals as defaults, such as function calls or subscript lookups or even simple attributes. If any solution is possible, it would require a way to differentiate between mutable and immutable objects, and evaluate the immutables for every call. This brings on more problems as to when you do the initial evaluation, if you then might do further evaluations depending on the results of the first. Any solution would be an unjust addition of expense to defaults. On 1/14/07, Chris Rebert <cvrebert@gmail.com> wrote:
If A.M. Kuchling's list of Python Warts is any indication, Python has removed many of the warts it once had. However, the behavior of mutable default argument values is still a frequent stumbling-block for newbies. It is also present on at least 3 different lists of Python's deficiencies ([0][1][2]).
Example of current, unintuitive behavior (snipped from [0]):
def popo(x=[]): ... x.append(666) ... print x ... popo() [666] popo() [666, 666] popo() [666, 666, 666]
Whereas a newbie with experience with immutable default argument values would, by analogy, expect:
popo() [666] popo() [666] popo() [666]
In scanning [0], [1], [2], and other similar lists, I have only found one mediocre use-case for this behavior: Using the default argument value to retain state between calls. However, as [2] comments, this purpose is much better served by decorators, classes, or (though less preferred) global variables. Other uses are alluded to be equally esoteric and unpythonic.
To work around this behavior, the following idiom is used: def popo(x=None): if x is None: x = [] x.append(666) print x
However, why should the programmer have to write this extra boilerplate code when the current, unusual behavior is only relied on by 1% of Python code?
Therefore, I propose that default arguments be handled as follows in Py3K: 1. The initial default value is evaluated at definition-time (as in the current behavior). 2. That in a function call where the caller has not specified a value for an optional argument, Python calls copy.deepcopy(initial_default_value), and fills in the optional argument with the resulting value.
This is fully backwards-compatible with the aforementioned workaround, and removes the need for the it, allowing one to write the first, simpler definition of popo().
Comments?
- Chris Rebert
[0] 10 Python pitfalls (http://zephyrfalcon.org/labs/python_pitfalls.html) [1] Python Gotchas (http://www.ferg.org/projects/python_gotchas.html#contents_item_6) [2] When Pythons Attack (http://www.onlamp.com/pub/a/python/2004/02/05/learn_python.html?page=2) _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://ironfroggy-code.blogspot.com/