On Mon, Nov 30, 2009 at 5:24 AM, spir <denis.s...@free.fr> wrote: > Hello, > > Below startup definitions: > > x = 1 > > def f(): > n = 1 > def g0(a): > print (x + n + a) > return g0 > > > I'm surprised the snippet below works as expected (py 2.6) without any trick: > > g = f() > g(1) # --> 3 > > This means a (real) closure is built for g0, or what?
Yes, Python has had real (read-only) closures since 2.1 when nested scopes where introduced: http://docs.python.org/dev/whatsnew/2.1.html#pep-227-nested-scopes Python 3 introduces the 'nonlocal' keyword which allows assignment to names in enclosing scopes, presumably ending at last the debate about whether Python has 'real' closures: http://www.python.org/dev/peps/pep-3104/ > Thought I would need instead to use the old trick of pseudo > default-parameters: > > def f(): > n = 1 > def g0(a, n=n, x=x): > print (x + n + a) > return g0 > > to let the inner func g0 "remember" outer values. Why is this idiom used, > then? Has something changed, or do I miss a relevant point? That has not been needed since 2.1 though it is still useful when closures are created in a loop (because closures are kind of late bound - I'm not sure the exact technical explanation): In [13]: def f(): ....: l = [] ....: for i in range(3): ....: def g(): ....: print i ....: l.append(g) ....: return l In [14]: for g in f(): g() ....: 2 2 2 But with the default argument it captures the value of i each time through the loop: In [15]: def f(): ....: l = [] ....: for i in range(3): ....: def g(i=i): ....: print i ....: l.append(g) ....: return l In [16]: for g in f(): g() ....: 0 1 2 > The bit below also works: > > x = 2 > ... > g(1) # --> 4 > > which seems to indicate python really embeds "symbolic references" (*) to > outer *variables*, when creating a closure for g0. Not "pointer references" > (**), otherwise the replacement of x would not be seen by the closure --like > in the case of default-parameter. In your first definition of f(), x is global and not included in the closure. This is the same behaviour you would have in older versions. In your second definition of f(), x is bound to a default argument and changing the global x doesn't change the result of g(). > Actually, I find this _Bad_. Obviously, the func's behaviour and result > depend on arbitrary external values (referentially opaque). What do you think? That is always the case when a function accesses globals. Globals are _Bad_, yes. Kent _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor