![](/img/trans.png)
[英]Using a base class function that takes parameters as a decorator for derived class function
[英]Using decorator from base class both in base class and derived class
我有一些帶有某些方法的python對象,在這些方法中,我希望在開始時進行一些檢查,根據此檢查,方法的代碼將運行,或者將引發執行。 我不希望在做裝飾器時在每個方法的開頭都復制“檢查”代碼,我還希望將裝飾器嵌入到類本身中,因為它與之密切相關。 所以基本上:
代替這個
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)
有人知道有任何干凈的方法嗎?
由於您希望將裝飾器放置在類中(而不是像我在評論中所建議的那樣,將它們放置在類中),因此下面顯示了一種實現方法。 它使裝飾器成為staticmethod
classmethod
,而不是classmethod
,並要求以一種稍微不尋常的方式使用它,但僅在類內使用。
有關使用這樣的裝飾器的必要性的更多信息,請參閱我的問題在類主體中調用類staticmethod?
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')
這具有使裝飾器的使用非常均勻的附加優點。
我的第一個問題是,我要這樣做嗎?
正如martineau在下面說的那樣,好的做法是將經典裝飾器放在課外。
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)
經典裝飾器在類創建期間被調用,該創建時間比創建實例早。 參考
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.