Закрытие не сформировано для внутренней функции - PullRequest
0 голосов
/ 12 июня 2018

Вот простая функция с локальной функцией:

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

Теперь я ожидаю, что локальная функция закроется через exp, но почему-то это не так.Когда я запускаю это:

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

я получаю None.Чего мне не хватает?

1 Ответ

0 голосов
/ 12 июня 2018

Нет замыкания, нет, потому что внутренняя функция имеет собственную переменную 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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...