在基础 class 和派生 class 中使用来自基础 class 的装饰器
Using decorator from base class both in base class and derived class
我有一些 python 对象和一些方法,我想在开始时对这些方法进行一些检查,根据此检查,方法的代码将 运行,或者执行将是提高。我不想在每个方法的开头复制 "check" 代码,尽管我做了一个装饰器,我还希望将装饰器嵌入到 class 本身中,因为它与它密切相关。所以基本上:
而不是这个
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 class 方法需要进行此检查,所以这就是为什么我不想不必要地复制代码。
我的第二个问题是,如果我按照我描述的方式去做,当我想从 class A 中导出 class 并执行相同的装饰检查。同样,我不想复制代码,所以我想重用基础 class A 中的装饰器来执行派生 class 中的检查。我阅读了有关将装饰器变成 @classmethod
的信息,但是当我这样做时,我可以在派生 class 中使用装饰器,但不能再在基础 class 中使用装饰器!
所以基本上我想要这样的东西:
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)
有人知道有什么干净的方法可以做到这一点吗?
My first question is, am I going about this right?
正如 martineau 在下面所说的,好的做法是将 classic 装饰器放在 class 之外。
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)
Classic decorator is called during class creation time, which is long before an instance is created. Reference
由于您更愿意将装饰器放在 class 内部(而不是像我在评论中建议的那样在它们外部),下面显示了一种方法。它使装饰器成为 staticmethod
而不是 classmethod
,并且需要以稍微不寻常的方式使用它,但仅在 class 的 范围内 。
有关像这样使用装饰器的必要性的更多信息,请参阅我的问题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__
并仍将定义保留在第一个 class 中的一种方法是推迟将它变成 staticmethod
直到 staticmethod
的最后=31=]定义:
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')
它还有一个额外的好处,就是使装饰器的使用非常统一。
我有一些 python 对象和一些方法,我想在开始时对这些方法进行一些检查,根据此检查,方法的代码将 运行,或者执行将是提高。我不想在每个方法的开头复制 "check" 代码,尽管我做了一个装饰器,我还希望将装饰器嵌入到 class 本身中,因为它与它密切相关。所以基本上:
而不是这个
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 class 方法需要进行此检查,所以这就是为什么我不想不必要地复制代码。
我的第二个问题是,如果我按照我描述的方式去做,当我想从 class A 中导出 class 并执行相同的装饰检查。同样,我不想复制代码,所以我想重用基础 class A 中的装饰器来执行派生 class 中的检查。我阅读了有关将装饰器变成 @classmethod
的信息,但是当我这样做时,我可以在派生 class 中使用装饰器,但不能再在基础 class 中使用装饰器!
所以基本上我想要这样的东西:
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)
有人知道有什么干净的方法可以做到这一点吗?
My first question is, am I going about this right?
正如 martineau 在下面所说的,好的做法是将 classic 装饰器放在 class 之外。
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)
Classic decorator is called during class creation time, which is long before an instance is created. Reference
由于您更愿意将装饰器放在 class 内部(而不是像我在评论中建议的那样在它们外部),下面显示了一种方法。它使装饰器成为 staticmethod
而不是 classmethod
,并且需要以稍微不寻常的方式使用它,但仅在 class 的 范围内 。
有关像这样使用装饰器的必要性的更多信息,请参阅我的问题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__
并仍将定义保留在第一个 class 中的一种方法是推迟将它变成 staticmethod
直到 staticmethod
的最后=31=]定义:
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')
它还有一个额外的好处,就是使装饰器的使用非常统一。