[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