Python3 无法将 @属性 作为装饰器参数传递
Python3 impossible to pass @property as decorator argument
我已经实现了装饰器,它可以接收额外的参数并希望将它与 class 方法一起使用。我想将 @属性 作为装饰器参数传递,但我得到的不是 @属性 结果:
<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()
两个问题:
- 如何正确传递 属性 以接收 @属性 结果而不是
<property object at 0x7f50f5195230>
- 如果代码在下方,是否可以将 class properties/methods 传递给装饰器?
一个property
对象是一个描述符。要从中获取值,您需要使用适当的实例调用其 __get__
方法。在您当前的代码中确定何时执行此操作并不容易,因为您的 Decorator
对象具有许多不同的角色。它既是装饰器工厂(使用 @Decorator(x)
行中的参数初始化),又是装饰器本身(使用要装饰的函数调用)。你给了它一个 __get__
方法,但我不希望它被使用,因为 Decorator
的实例永远不会被分配给 class 变量(只有包装函数从 __call__
).
返回
无论如何,这是一个修改版本,其中 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
我已经实现了装饰器,它可以接收额外的参数并希望将它与 class 方法一起使用。我想将 @属性 作为装饰器参数传递,但我得到的不是 @属性 结果:
<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()
两个问题:
- 如何正确传递 属性 以接收 @属性 结果而不是
<property object at 0x7f50f5195230>
- 如果代码在下方,是否可以将 class properties/methods 传递给装饰器?
一个property
对象是一个描述符。要从中获取值,您需要使用适当的实例调用其 __get__
方法。在您当前的代码中确定何时执行此操作并不容易,因为您的 Decorator
对象具有许多不同的角色。它既是装饰器工厂(使用 @Decorator(x)
行中的参数初始化),又是装饰器本身(使用要装饰的函数调用)。你给了它一个 __get__
方法,但我不希望它被使用,因为 Decorator
的实例永远不会被分配给 class 变量(只有包装函数从 __call__
).
无论如何,这是一个修改版本,其中 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