Ваши части кода выполняются в разное время.
Функция внешнего декоратора, где вы печатаете «1», вызывается там, где вы читаете @decorator3()
. Результат вызова этой функции, decorator
, затем немедленно применяется к декорированной функции (соответственно, метод), где вы читаете "2".
В вашем случае внутренний декоратор заменяет метод на другая функция, которая вызывает оригинальный метод. Только если вы вызовете это, вы достигнете «3».
Итак:
- в 1, вы ничего не знаете о своей функции.
- в 2 вы знаете свою функцию, но не в каком классе она живет.
- в 3, вы знаете свой объект, но только если вызывается ваша функция.
Вам нужно решить что именно вы хотите сделать: согласно вашему описанию, вы хотите пометить функции. Это то, что вы прекрасно можете сделать в «2».
Вы говорите:
Мне нужно отслеживать методы, которые я позже украсил в коде. По сути, я украшаю его, чтобы «пометить» метод, и у меня есть несколько классов с разными методами, которые мне нужно пометить. Я буду вызывать decorator3 в других классах, поэтому я не вижу, как поможет установка декоратора в init . Редактируя исходный класс, я позже могу поместить метод в словарь, который, как я надеялся, сделает декоратор.
Может быть, работает следующее:
import functools
def method_flagger(function):
function._flag = "flag"
return function
list_of_methods = []
def flag_reader(function):
@functools.wraps(function)
def wrapper(self, *args):
for i in dir(self.__class__):
#for i, j in self.__class__.__dict__.items():
method_wrapper = getattr(self, i)
if hasattr(getattr(self, i), "_flag"):
list_of_methods.append((self, i))
return function(self, *args)
return wrapper
class Test:
@flag_reader
def __init__(self):
self.a = "test"
@method_flagger
def test(self):
print(self.a)
@method_flagger
def test2(self):
print(self.a)
t1 = Test()
t2 = Test()
#t.test()
#print(t.__test__)
print(list_of_methods)
Это дает мне вывод
[(<__main__.Test object at 0x000001D56A435860>, 'test'), (<__main__.Test object at 0x000001D56A435860>, 'test2'), (<__main__.Test object at 0x000001D56A435940>, 'test'), (<__main__.Test object at 0x000001D56A435940>, 'test2')]
, поэтому для каждого экземпляра затронутого объекта и каждой украшенной функции мы получаем кортеж, обозначающий их обоих.