On Jan 1, 6:48 pm, "Gabriel Genellina" <[EMAIL PROTECTED]> wrote: > En Tue, 01 Jan 2008 15:45:00 -0200, bukzor <[EMAIL PROTECTED]> > escribi�: [...] > >> 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
Let me say again that I believe the current behaviour to be the correct one. But I don't think this 'early binding' is critical for this sort of example. There are lots of ways to solve the problem of having persistent state across function calls, for example: * using classes * using modules * or simply nested functions: def getfoo(z): def foo(a): print a + z return foo >>> z = 1 >>> foo = getfoo(z) >>> z = None >>> foo(3) 4 And with nonlocal, we could even modify z inside foo and this change would persist across calls. This will be a much cleaner solution than the current def bar(x, y, _hidden=[startvalue]). Also, note that it's easy to implement default arguments in pure python-without-default-arguments using a decorator: def default(**defaults): defaults = defaults.items() def decorator(f): def decorated(*args, **kwargs): for name, val in defaults: kwargs.setdefault(name, val) return f(*args, **kwargs) return decorated return decorator Here is your example: >>> z=1 >>> @default(z=z) ... def foo(a, z): ... print a + z ... >>> z=None >>> foo(3) 4 Another example, using mutables: >>> @default(history=[]) ... def bar(x, history): ... history.append(x) ... return list(history) ... >>> map(bar, 'spam') [['s'], ['s', 'p'], ['s', 'p', 'a'], ['s', 'p', 'a', 'm']] -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list