Как указано в документе memoization example в документах decorator
, вы не можете использовать подход вложенных функций для реализации memoization, сохраняя при этом подпись функции. Вместо этого, вы должны поднять внутреннюю функцию, и затем создать тривиальную функцию декоратора:Почему модуль декоратора заставляет меня поднять внутреннюю функцию на внешний уровень?
def _memoize(func, *args, **kwargs):
# the memoization code
def memoize(f):
f.cache = {}
return decorator(_memoize, f)
Почему я не могу использовать внутреннюю функцию? Или документы вводят в заблуждение, то есть есть возможность использовать внутреннюю функцию с @decorator
? Есть ли какая-то практическая причина, основанная на реализации, почему это так, или я действительно вынужден сделать это чужой путь? Я ненавижу вспомогательные функции и хотел бы избежать этого подхода, если это возможно; если есть хак, чтобы заставить его работать (без, конечно, самого написания с нуля), я хотел бы услышать, что это такое.
Следует отметить, что без необходимости инициализации cache
или любого другого кода, который не был бы частью внутренней функции, конечно, @decorator
работает просто отлично, не используя внешнюю функцию вообще (но затем снова , зачем использовать внутреннюю функцию, если у вас нет кода вне внутренней функции?).
Я не понимаю, что вы подразумеваете под «Я ненавижу вспомогательные функции». '_memoize' - вспомогательная функция, и фактически точная вспомогательная функция _same_, будь то на верхнем уровне или вложенная внутри' memoize'. – abarnert
@abarnert Я понимаю это; Наверное, я хотел сказать, что я ненавижу вспомогательные функции, которые становятся доступными по имени, когда вы делаете «из импорта модуля». Это приводит меня к вопросу: если это тот же самый код, почему меня принуждают сделать это одним способом без возможности другого?Я попытался вернуть «декоратор (внутренний, func)» и т. П. Из внешней функции, действующей как декоратор, и не повезло. Нет никакой разницы, кроме того, если вы импортируете мой модуль, вы можете получить сломанную функцию '_memoize', которая выдает исключение, если вы передадите ему функцию без атрибута' cache'. – 2rs2ts
Ну, есть стандартные способы избежать этого. Часто просто отговаривайте «от импорта модуля». Если это не подходит, укажите явный '__all__'. (Если вы действительно этого захотите, вы можете просто «деблокировать» функцию после того, как вы закончите с ней, или спрячьте ее где-нибудь и т. Д.). Но в этом случае ... атрибуты модуля верхнего уровня, начинающиеся с одного подчеркивания, - это _already_ не импортируется 'из импорта модуля * ', поэтому проблема даже не возникает. – abarnert