簡體   English   中英

使用將參數作為派生類函數的修飾符的基類函數

[英]Using a base class function that takes parameters as a decorator for derived class function

我覺得我在處理常規函數時非常了解使用裝飾器,但是在派生類中使用裝飾器的基類方法和將參數傳遞給所述裝飾器之間,我不知道下一步該怎么做。 這是一段代碼。

class ValidatedObject:
    ...

    def apply_validation(self, field_name, code):
        def wrap(self, f):
            self._validations.append(Validation(field_name, code, f))
            return f
        return wrap


class test(ValidatedObject):
    ....
    @apply_validation("_name", "oh no!")
    def name_validation(self, name):
        return name == "jacob"

如果按原樣嘗試,則會發現找不到“ apply_validation”。
如果我使用@self.apply_validation嘗試,則@self.apply_validation “自我”。
我也一直在使apply_validation成為一個沒有成功的類方法。

有人可以解釋我在做什么錯,以及解決此問題的最佳方法嗎? 謝謝。

只是在類方法上使用裝飾器的示例:

from functools import wraps

def VALIDATE(dec):
    @wraps(dec)
    def _apply_validation(self, name):
        self.validate(name)
        return dec(self, name)
    return _apply_validation

class A:
    def validate(self, name):
        if name != "aamir":
            raise Exception, 'Invalid name "%s"' % name

class B(A):

    @VALIDATE
    def name_validation(self, name):
        return name

b = B()
b.name_validation('jacob') # should raise exception

您遇到的問題是apply_validation是一個方法,這意味着您需要在ValidatedObject的實例上調用它。 不幸的是,在調用它的時候(在test類的定義期間),沒有合適的實例可用。 您需要一種不同的方法。

最明顯的一個方法是使用一個元類來搜索其實例字典(實際上是類字典),並根據找到的內容設置_validations變量。 您仍然可以使用裝飾器,但是它可能應該是全局函數或靜態方法,並且需要以不同的方式工作。 這是一些代碼,使用元類和添加函數屬性的裝飾器:

class ValidatedMeta(type):
    def __new__(meta, name, bases, dct):
        validations = [Validation(f._validation_field_name, f._validation_code, f)
                       for f in dct.values if hasattr(f._validation_field_name)]
        dct["_validations"] = validations
        super(ValidatedMeta, meta).__new__(meta, name, bases, dct)

def apply_validation(field_name, code):
    def decorator(f):
        f._validation_field_name = field_name
        f._validation_code = code
        return f
    return decorator

def ValidatedObject(metaclass=ValidatedMeta):
    pass

class test(ValidatedObject):
    @apply_validation("_name", "oh no!")
    def name_validation(self, name):
        return name == "jacob"

此代碼運行后, test._validations將為[Validation("_name", "oh no!", test.name_validation)] 請注意,傳遞給Validation是未綁定的,因此您在調用它時需要自己傳遞一個self參數(或者刪除self參數並更改apply_validation創建的裝飾器以返回staticmethod(f) )。 。

如果您在繼承層次結構的多個級別上定義了驗證方法,則此代碼可能無法執行您想要的操作。 上面編寫的元類僅檢查直接類的dict是否具有適當屬性的方法。 如果您還需要在_validations包括繼承的方法, _validations可能需要修改ValidatedMeta.__new__的邏輯。 可能是要走的最簡單的方法是看_validations在屬性bases並連接列表在一起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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