Bizarre behavior with mutable default arguments

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Tue Jan 1 19:48:33 CET 2008


En Tue, 01 Jan 2008 15:45:00 -0200, bukzor <workitharder at gmail.com>  
escribi�:
> On Jan 1, 9:00 am, bukzor <workithar... at gmail.com> wrote:
>> On Dec 31 2007, 1:30 pm, "Chris Mellon" <arka... at gmail.com> wrote:
>>
>> > And also removing the only way you can currently do early binding in
>> > Python. I agree that it's a gotcha, but unless someone comes up with
>> > an answer to the following questions, I'll stick with the status quo
>> > (Note that this is not blind Python group-think as a previous poster
>> > implied, but a pragmatic decision that this is the most practical
>> > solution):
>>
>> > a) If we don't evaluate default arguments at function compilation,
>> > when do we do it?
>> > b) If you do it at call time, how do you implement early binding?
>>
>> I'm confused by what you mean by 'early binding'. Can you give a quick-
>> n-dirty example?
> Is an 'early bound' variable synonymous with a 'static' variable (in
> C)?

No. It means, in which moment the name gets its value assigned. Usually  
Python does "late binding", that is, names are resolved at the time the  
code is executed, not when it's compiled or defined.
Consider this example:

z = 1
def foo(a)
   print a+z
foo(3) # prints 4
z = 20
foo(3) # prints 23

The second time it prints 23, not 4, because the value for z is searched  
when the code is executed, so the relevant value for z is 20.
Note that if you later assign a non-numeric value to z, foo(3) will fail.

If you want to achieve the effect of "early binding", that is, you want to  
"freeze" z to be always what it was at the time the function was defined,  
you can do that using a default argument:

z = 1
def foo(a, z=z)
   print a+z
z = None
foo(3) # prints 4

This way, foo(3) will always print 4, independently of the current value  
of z. Moreover, you can `del z` and foo will continue to work.

This is what I think Chris Mellon was refering to. This specific default  
argument semantics allows one to achieve the effect of "early binding" in  
a language which is mostly "late binding". If someone changes this, he has  
to come with another way of faking early binding semantics at least as  
simple as this, else we're solving an [inexistant for me] problem but  
creating another one.

-- 
Gabriel Genellina




More information about the Python-list mailing list