簡體   English   中英

在基類和派生類中使用基類的裝飾器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM