4

Here's a simple function with a local function:

def raise_to(exp): def raise_to_exp(x, exp): return pow(x, exp) return raise_to_exp 

Now I expect the local function to close over exp, but somehow it doesn't. When I run this:

square = raise_to(2) print(square.__closure__) 

I get None. What am I missing?

1 Answer 1

4

There is no closure, no, because the inner function has it's own local exp variable; you gave it a parameter by that name. The parameter masks the name in the outer scope, so no closure is created for it. The function that is returned requires two arguments, and the argument to raise_to() is simply ignored:

>>> from inspect import signature >>> def raise_to(exp): ... def raise_to_exp(x, exp): ... return pow(x, exp) ... return raise_to_exp ... >>> signature(raise_to(2)) <Signature (x, exp)> >>> square = raise_to(2) >>> square(5) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: raise_to_exp() missing 1 required positional argument: 'exp' >>> square(5, 3) 125 >>> raise_to('This is ignored, really')(5, 3) 125 

Remove the exp parameter from the inner function if you wanted that to be taken from the outer function:

def raise_to(exp): def raise_to_exp(x): return pow(x, exp) return raise_to_exp 

Now exp is a closure:

>>> def raise_to(exp): ... def raise_to_exp(x): ... return pow(x, exp) ... return raise_to_exp ... >>> raise_to(2).__closure__ (<cell at 0x11041a978: int object at 0x10d908ae0>,) >>> raise_to.__code__.co_cellvars ('exp',) 

The co_cellvars attribute on a code object gives you the names of any closed-over variable in the outer scope.

The function that is returned takes one argument, and the argument to raise_to() is now actually used:

>>> raise_to(2)(5) 25 >>> raise_to('Incorrect type for pow()')(5) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in raise_to_exp TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'str' 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.