[Python-3000] default argument surprises

Nick Coghlan ncoghlan at gmail.com
Wed Aug 27 23:27:07 CEST 2008


Chris Rebert wrote:
> On Wed, Aug 27, 2008 at 11:01 AM, Brett Cannon <brett at python.org> wrote:
>> On Wed, Aug 27, 2008 at 9:29 AM, Sam Bishop <samuel.j.bishop at gmail.com> wrote:
>>> On Tue, Aug 26, 2008 at 8:31 PM, Chris Rebert <cvrebert at gmail.com> wrote:
>>>> You might then be interested in the following related discussions from
>>>> last year wherein I proposed something extremely similar:
>>>>
>>>> [Python-ideas] proto-PEP: Fixing Non-constant Default Arguments
>>>> http://mail.python.org/pipermail/python-ideas/2007-January/000121.html
>>>>
>>>> [Python-3000] pre-PEP: Default Argument Expressions
>>>> http://mail.python.org/pipermail/python-3000/2007-February/005712.html
>>> Hmm...  That's too bad.  I like your PEP.  :)
>>>
>>> I disagree with Guido's comment about this being related to class
>>> variables, from a newbie's point of view anyway.  Classes introduce a
>>> namespace and functions introduce a scope.  What surprises me is that
>>> functions seem to introduce two scopes: one for variables declared as
>>> formal parameters and one for variables assigned to within the
>>> function.
>>>
>> But the point is that this is a newbie POV that is based on a
>> misunderstanding. It's going to be nearly impossible to remove all
>> possible gotchas from the language based on what a proto-typical
>> newbie might get tripped up on when it is based on a misunderstanding.
>> If you don't view everything but function/method bodies as executed
>> code, then you have a misconception about how Python works.
>>
>> Perhaps this can be better explained in the tutorial or language
>> reference. But because something is not being communicated well by the
>> documentation does not mean it needs to be changed.
>>
>> -Brett
>>
> 
> Normally I'd agree, but in this case there seems to be no significant
> advantage to the current behavior over the hypothetical behavior
> beyond simply inertia and a slight possible performance advantage.
> While the hypothetical behavior would obviate the extremely common
> "x=None): if x is None: x = foo" idiom AND prevent the sorts of
> confusion that the OP experienced, the current behavior is mostly only
> advantageous when using function arguments as caches, except that
> there are much better and clearer ways to do these caches!

Late binding default arguments would do some fairly bad things to nested
functions such as preventing the use of class attributes when defining
method default arguments, and having the default value reflect the last
bound value of a function local, instead of the value bound at the time
when the nested function is defined. It would also result in closures
being created in many cases where they aren't currently needed (i.e.
when the only reference to variables in the containing scope is via
default argument values).

The speed impact of late binding is also non-trivial, since the cost of
the default argument evaluation would then be incurred every time the
function is called, instead of just once when the function is defined.

Given that both approaches (binding at definition execution time and
binding afresh at each call) have their "gotchas", and the latter offers
no compelling advantages over the former and comes with some major
disadvantages (such as breaking every piece of Python code that relies
on the current behaviour and slowing down calls to all functions with
default arguments), I'd say our reasons for leaving it the way it is are
a bit stronger than is suggested by the "inertia and a slight possible
performance advantage" phrasing. Backwards compatibility and speed
matter, and neither should be thrown away just because novices find
something a little confusing before they understand how it works.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
            http://www.boredomandlaziness.org


More information about the Python-3000 mailing list