Есть ли чистый способ, чтобы декоратор вызывал метод экземпляра в классе только в момент создания экземпляра класса?Вызов методов экземпляра Python в декораторах функций
class C:
def instance_method(self):
print('Method called')
def decorator(f):
print('Locals in decorator %s ' % locals())
def wrap(f):
print('Locals in wrapper %s' % locals())
self.instance_method()
return f
return wrap
@decorator
def function(self):
pass
c = C()
c.function()
Я знаю, что это не работает, потому что self
не определена в точке decorator
называется (так как он не вызываются как метод экземпляра, пока нет доступной ссылки на класс). Затем я пришел к этому решению:
class C:
def instance_method(self):
print('Method called')
def decorator():
print('Locals in decorator %s ' % locals())
def wrap(f):
def wrapped_f(*args):
print('Locals in wrapper %s' % locals())
args[0].instance_method()
return f
return wrapped_f
return wrap
@decorator()
def function(self):
pass
c = C()
c.function()
Это использует тот факт, что я знаю, первый аргумент любого метода экземпляра будет self
. Проблема с тем, как определяется эта оболочка, заключается в том, что метод экземпляра вызывается каждый раз, когда выполняется функция, чего я не хочу. Затем я подошел со следующим небольшим изменением, которое работает:
class C:
def instance_method(self):
print('Method called')
def decorator(called=[]):
print('Locals in decorator %s ' % locals())
def wrap(f):
def wrapped_f(*args):
print('Locals in wrapper %s' % locals())
if f.__name__ not in called:
called.append(f.__name__)
args[0].instance_method()
return f
return wrapped_f
return wrap
@decorator()
def function(self):
pass
c = C()
c.function()
c.function()
Теперь функция только вызывается один раз, но мне не нравится тот факт, что эта проверка должна происходить каждый раз, когда функция вызывается. Я предполагаю, что нет никакого способа обойти это, но если у кого есть какие-то предложения, я бы хотел их услышать! Спасибо :)
Если вы используете (AFAIK) python 2.5+, вы должны, вероятно, создать класс подкласса: 'class C (object):' для получения преимуществ классов нового стиля. –
Ваши имена ошибочны. То, что вы называете «декоратором», на самом деле является декоратором * factory *, и то, что вы называете 'wrap', является декоратором. Кроме того, использование 'called = []' несколько обманчиво; хотя в этом случае это правильно. – katrielalex
@katriealex Достаточно честный. Недавно я познакомился с этим синтаксисом для декораторов. У меня был этот пример внутри другой базы кода, поэтому я просто быстро переименовал функции для очистки вещей. Спасибо за разъяснение хотя :) –