我有一些python对象,其中有一些方法我想在开始时进行一些检查,取决于这个检查,方法的代码会运行,或者会引发一个execption。而不是复制"检查"代码在每个方法的开头我虽然做了一个装饰器,但我也希望装饰器嵌入到类本身中,因为它与它密切相关。所以基本上:
而不是
class A(object):
def a_method(self):
if self.check_var is True:
(some_code)
else:
raise Exception
我想要这个
class A(object):
def decorator(function):
def function_wrapper(self, *args, **kwargs):
if self.check_var is True:
return function(self, *args, **kwargs)
else:
raise Exception
return function_wrapper
@decorator
def a_method(self):
(some_code)
我的第一个问题是,我是否正确行事?或者,还有更好的方法。我有很多A类的方法需要进行此检查,这就是为什么我不想不必要地复制代码。
我的第二个问题是,如果我按照我描述的方式进行此操作,当我想从A类派生一个类并且执行相同的装饰器检查时,我会遇到问题。我再也不想复制代码,因此我想重用基类A中的装饰器来对派生类中的执行进行检查。我读过关于将装饰器变成@classmethod
但是当我这样做时,我能够在派生类中使用装饰器而不再在基类中使用!
所以基本上我想要这样的东西:
class A(object):
@classmethod #maybe
def decorator(function):
def function_wrapper(self, *args, **kwargs):
if self.check_var is True:
return function(self, *args, **kwargs)
else:
raise Exception
return function_wrapper
@decorator
def a_method(self):
(some_code)
class B(A):
@decorator
def b_method(self):
(some_code)
有人知道有什么干净的方法吗?
答案 0 :(得分:4)
由于您希望将装饰器放在类中(而不是像我在注释中建议的那样在它们之外),下面显示了一种方法。它使装饰器成为staticmethod
而不是classmethod
,并且需要以稍微不同寻常的方式使用它,但只有在类中。
有关使用像这样的装饰器的必要性的更多信息,请参阅我的问题Calling class staticmethod within the class body?
class A(object):
@staticmethod
def decorator(function):
def function_wrapper(*args, **kwargs):
print('in function_wrapper')
return function(*args, **kwargs)
return function_wrapper
@decorator.__func__ #### Note unusual decorator usage inside defining class
def a_method(self):
print('in a_method')
class B(A):
@A.decorator #### Normal decorator usage outside defining class
def b_method(self):
print('in b_method')
避免使用__func__
并仍然将定义保留在第一个类中的一种方法是推迟将其转换为staticmethod
,直到类定义的最后:
class A(object):
def decorator(function):
def function_wrapper(*args, **kwargs):
print('in function_wrapper')
return function(*args, **kwargs)
return function_wrapper
@decorator
def a_method(self):
print('in a_method')
decorator = staticmethod(decorator) #### convert for use outside this class
class B(A):
@A.decorator
def b_method(self):
print('in b_method')
另一种避免__func__
的方法是这样的:
class A(object):
class Check:
@staticmethod
def decorator(function):
def function_wrapper(*args, **kwargs):
print('in function_wrapper')
return function(*args, **kwargs)
return function_wrapper
@Check.decorator
def a_method(self):
print('in a_method')
class B(A):
Check = A.Check
@Check.decorator
def b_method(self):
print('in b_method')
另外一个优点是使装饰器的使用非常均匀。
答案 1 :(得分:0)
我的第一个问题是,我是否正确行事?
正如马蒂诺在下面所说,好的做法是把经典装饰师放在课外。
def get_decorator(function, argument):
def function_wrapper(*args, **kwargs):
if argument is True:
return function(*args, **kwargs)
else:
raise Exception
return function_wrapper
class A(object):
def __init__(self):
self.check_var = True
self.a_method = get_decorator(self.a_method, self.check_var)
def a_method(self):
(whatever)
class B(A):
def __init__(self):
super(B, self).__init__()
self.b_method = get_decorator(self.b_method, self.check_var)
def b_method(self):
(whatever)
在类创建期间调用经典装饰器,这是在创建实例之前很久。 Reference