[Python-ideas] Tweaking closures and lexical scoping to include the function being defined
Arnaud Delobelle
arnodel at gmail.com
Sat Oct 1 23:03:10 CEST 2011
On 1 October 2011 21:36, Ron Adam <ron3200 at gmail.com> wrote:
[...]
> def supply_y(y):
> def _(func):
> def wrapper(x):
> return func(x, y)
> return wrapper
> return _
>
> @supply_y(2)
> def add(x, y):
> return x + y
>
>
> Pep 318 says it should translate to ...
>
> def add(x, y):
> return x + y
> add = supply_y(2)(add)
>
> add(3) ---> 5 # call wrapper with x, which calls add with (x, y)
>
>
> But the behavior is as you suggest...
>
> _temp = suppy_y(2)
> def add(x, y):
> return x + y
> add = _temp(add)
>
> add(3) ---> 5
>
>
> This isn't what Pep 318 says it should be.
>
> Is this intentional, and does Pep 318 need updating?
>
> Or an unintended implementation detail?
>
> If it wasn't intended, then what?
I don't know if it is intentional, but it is probably a consequence of
the fact that the CALL_FUNCTION opcode expects the function below its
arguments in the stack. So the most concise way of implementing
@<decorator_expression>
def f(x):
....
is to:
1. evaluate <decorator_expression> an push the result on the stack
2. create function f and push it on the stack
3. execute CALL_FUNCTION
4. store the result in 'f'
If you swap steps 1 and 2, then you need to add a new step:
2.5 execute ROT_TWO (swap TOS and TOS1)
--
Arnaud
More information about the Python-ideas
mailing list