[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