[Python-ideas] Allow lambda decorators
Bruce Frederiksen
dangyogi at gmail.com
Mon Feb 9 18:33:52 CET 2009
Carl Johnson wrote:
> A few months back there was a discussion of how code like this gives
> "surprising" results because of the scoping rules:
>
> >>> def func_maker():
> ... fs = []
> ... for i in range(10):
> ... def f():
> ... return i
> ... fs.append(f)
> ... return fs
> ...
> >>> [f() for f in func_maker()]
> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
>
> [...]
>
> Thinking about it some more, I've realized that the change I proposed
> is unnecessary, since we already have the decorator syntax. So, for
> example, the original function can be made to act with the "expected"
> scoping by using an each_in function defined as follows:
>
> >>> def each_in(seq):
> ... return lambda f: [f(item) for item in seq]
> ...
> >>> def func_maker():
> ... @each_in(range(10))
> ... def fs(i):
> ... def f():
> ... return i
> ... return f
> ... return fs #Warning, fs is a list, not a function!
> ...
> >>> [f() for f in func_maker()]
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>
It seems like a more general solution to the variable scoping in for
statements would be:
>>> def for_each(body):
... def loop(seq):
... for i in seq: body(i)
... return loop
>>> @for_each
... def body(i):
... def f(): return i
... fs.append(f)
>>> fs = []
>>> body(range(10))
>>> [f() for f in fs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
But it's not clear that the decorator is even required:
>>> def repeat(body, seq):
... for i in seq: body(i)
>>> def body(i):
... def f(): return i
... fs.append(f)
>>> fs = []
>>> repeat(body, range(10))
>>> [f() for f in fs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The repeat function should be fully general.
-bruce
More information about the Python-ideas
mailing list