Начиная с 2.4 (2.6 для классов), python позволяет вам украшать функцию другой функцией:
def d(func): return func
@d
def test(first): pass
Это удобный синтаксический сахар.Вы можете делать всякие аккуратные вещи с декораторами, не беспорядок.Однако, если вы хотите узнать оригинальную функцию, которая была украшена, вы должны прыгать через обручи (например, Cls.method.__func__.__closure__[0].cell_contents
или хуже).
Я обнаружил, что желаю лучшего способа и обнаружил, что были некоторыеобсуждение python-dev о добавлении переменной с именем __decorated__
в функцию [new], возвращаемую декоратором.Тем не менее, похоже, что это никуда не делось.
Будучи приключенческим человеком и имея довольно большой опыт работы с Python около 4 лет, я подумал, что буду искать реализацию __decorated__
в исходном коде компилятора python,просто чтобы посмотреть, как это происходит.
Если честно, я никогда не углублялся в C под капотом, поэтому мои первые часы просто пытались понять, как работает лежащий в основе C-код.Итак, во-первых, , какие будут лучшие ресурсы, чтобы разобраться, что мне нужно изменить / добавить для __decorator__
?
Во-вторых, если декоратор возвращает новую функцию, тогда __decorated__
просто вернет оригинальную декорированную функцию.Однако, если декоратор возвращает исходную функцию, что должно произойти?Вот три варианта, которые я могу придумать (третий - мой любимый):
- Не добавляйте
__decorator__
. - Добавьте
__decorator__
, но установите для него значение Нет. - Добавьте
__decorator__
и установите его на исходную функцию в любом случае.
Так что, если это произойдет, Как вы думаете, что будет лучшим вариантом?
ОБНОВЛЕНИЕ:
Кто-то еще привлек мое внимание сценарий, который я пропустил.Что происходит, когда декоратор не возвращает ни оригинальную функцию, ни функцию, которая оборачивает оригинал?На этом этапе ничто не содержит ссылку на исходную функцию, и она будет собирать мусор.(Спасибо Нечетное мышление !)
Так что в этом случае, я думаю, что я все еще пошел бы с третьим вариантом.Объект, возвращаемый декоратором, получит имя __decorated__
, которое ссылается на исходную функцию.Это будет означать, что он не будет собирать мусор.
Мне кажется странным, что функция из определения класса полностью исчезнет, потому что вы украсили ее.На мой взгляд, это еще одна причина использовать атрибут __decorated__
для каждого декоратора.Тем не менее, более вероятно, что моя интуиция ошибочна и что нынешнее поведение - это то, чего большинство людей ожидают. Есть мысли?
ps это продолжение более раннего, более общего вопроса , который у меня был.Я также получил дополнительную информацию о первой части с отдельным постом .