Как я могу определить метод декоратора внутри класса?
Возможный дубликат:
Может ли метод класса быть декоратором?
здесь пример.
class myclass:
def __init__(self):
self.start = False
def check(self):
return not self.start
def doA(self):
if self.check():
return
print('A')
def doB(self):
if self.check():
return
print('B')
как вы видите, я хочу написать действие проверки в стиле декоратора, но после того, как я много раз пробовал, я обнаружил, что могу написать метод за пределами моего класса. Попробуйте научить меня, как писать его внутри класса, спасибо
изменить:
Я могу написать код следующим образом:
def check(func):
def checked(self):
if not self.start:
return
func(self)
return checked
class myclass:
def __init__(self):
self.start = False
@check
def doA(self):
print('A')
@check
def doB(self):
print('B')
a = myclass()
a.doA()
a.doB()
a.start = True
a.doA()
a.doB()
но я не думаю, что это хорошая практика, я хочу определить метод проверки внутри моего класса.
Ответы
Ответ 1
Итак, вы хотите использовать декораторы внутри класса на одном (или более) методах членов?
Если это так, я понимаю, чего вы хотите, я не понимаю, зачем вам это нужно?
Нет никаких веских причин для этого. a class
- это аккуратный контейнер, вам не нужны декораторы, как методы класса, которые вы можете просто вызвать один метод из другого. Это случай увлеченности decorators
?
Ответ 2
В то время как я не думаю, что это абсолютно необходимо все время, вот как вы могли бы сделать декоратор в своем классе. Это немного более громоздко из-за того, как методы впоследствии привязаны к self
. Обычно с декораторами с обычными функциями вам не нужно беспокоиться об этом.
Требования:
- Декоратор должен быть определен первым, прежде чем методы, которые будут его использовать.
- Для правильного сохранения связанных методов необходимо использовать
functools.wrap
Пример:
from functools import wraps
class myclass:
def __init__(self):
self.start = False
def _with_check(f):
@wraps(f)
def wrapped(inst, *args, **kwargs):
if inst.check():
return
return f(inst, *args, **kwargs)
return wrapped
def check(self):
return self.start
@_with_check
def doA(self):
print('A')
@_with_check
def doB(self):
print('B')
Я сделал его защищенным членом, так как на самом деле это не то, что кому-то еще нужно использовать за пределами класса. И он по-прежнему сохраняет ваш общедоступный вызов check()
для использования сам по себе. Декоратор просто обертывает его вызовом перед вызовом целевого метода.
Ответ 3
Если вам нужно изменить количество или все методы в классе, но вы хотите применить это изменение поведения к этому классу и его подклассам, просто используйте __getattr__()
и/или __getattribute__()
для вместо этого выполните свое поведение.
Ответ 4
Я думаю, это то, о чем вы просите. Размещение декоратора @property до проверки def (тот же отступ) делает так, чтобы вы могли получить доступ к вычисленному значению проверки() в качестве проверки атрибута, а затем изменить свои методы doA()/doB(), чтобы self.check выглядит как доступ к атрибуту.
class myclass:
def __init__(self):
self.start = False
@property
def check(self):
return not self.start
def doA(self):
if self.check:
return
print('A')
def doB(self):
if self.check:
return
print('B')