簡體   English   中英

Python3 無法將 @property 作為裝飾器參數傳遞

[英]Python3 impossible to pass @property as decorator argument

我已經實現了可以接收額外的 arguments 並希望將其與 class 方法一起使用的裝飾器。 我想將@property 作為裝飾器參數傳遞,但我得到的不是@property 結果:

<property object at 0x7f50f5195230>

這是我的裝飾器:

class Decorator(object):
    def __init__(self, some_arg):
        self.func = None
        self.some_arg = some_arg

    def __get__(self, instance, owner):
        import functools
        return functools.partial(self.__call__, instance)

    def __call__(self, func):
        self.func = func
        def wrapper(*args, **kwargs):
            return self._process_sync(*args, **kwargs)
        return wrapper

    def _process_sync(self, *args, **kwargs):
        try:
            print(self.some_arg)
            return self.func(*args, **kwargs)
        except Exception as e:
            print(e)
            return None

我的測試 class:

class Test(object):
    @property
    def some_data(self):
        return {'key': 'value'}

    @Decorator(some_data)
    def some_method(self):
        print('method output')
        return None

用法:

test = Test()
test.some_method()

兩個問題:

  1. 如何正確傳遞屬性以接收 @property 結果而不是<property object at 0x7f50f5195230>
  2. 如果 class 屬性/方法在代碼下方,是否可以將它們傳遞給裝飾器?

property object 是一個描述符。 要從中獲取值,您需要使用適當的實例調用其__get__方法。 在您當前的代碼中確定何時執行此操作並不容易,因為您的Decorator object 有很多不同的角色。 它既是裝飾器工廠(使用@Decorator(x)行中的參數進行初始化),又是裝飾器本身(使用 function 進行裝飾)。 你給了它一個__get__方法,但我不希望它被使用,因為Decorator的實例永遠不會被分配給 class 變量(只有從__call__返回的包裝器 function )。

無論如何,這是一個修改后的版本,其中Decorator處理了描述符協議本身的幾乎所有部分:

class Decorator:
    def __init__(self, arg):
        self.arg = arg      # this might be a descriptor, like a property or unbound method

    def __call__(self, func):
        self.func = func
        return self         # we still want to be the descriptor in the class

    def __get__(self, instance, owner):
        try:
            arg = self.arg.__get__(instance, owner)   # try to bind the arg to the instance
        except AttributeError: # if it doesn't work, self.arg is not a descriptor, that's OK
            arg = self.arg

        def wrapper(*args, **kwargs):   # this is our version of a bound method object
            print(arg) # do something with the bound arg here
            return self.func.__get__(instance, owner)(*args, **kwargs)

        return wrapper

暫無
暫無

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

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