Нет замыкания, нет, потому что внутренняя функция имеет собственную переменную local exp
;Вы дали ему параметр с таким именем.Параметр маскирует имя во внешней области видимости, поэтому закрытие для него не создается.Возвращаемая функция требует двух аргументов, а аргумент raise_to()
просто игнорируется:
>>> 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
Удалите параметр exp
из внутренней функции, если вы хотите, чтобы этобыть взятым из внешней функции:
def raise_to(exp):
def raise_to_exp(x):
return pow(x, exp)
return raise_to_exp
Теперь exp
является закрытием:
>>> 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',)
Атрибут co_cellvars
в объекте кода дает вам имена любых закрытыхпеременная over во внешней области видимости.
Возвращаемая функция принимает один аргумент, и теперь фактически используется аргумент raise_to()
:
>>> 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'