为什么当 @property 装饰器时下面的代码不起作用 应用于已经用
@property
修饰的方法上? (我使用的是Python 3.10。)
# Define a decorator
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Decorator applied")
return func(*args, **kwargs)
return wrapper
# Apply the decorator over the method
class MyClass:
@my_decorator
@property
def x(self):
return 42
# Test the decorated method
obj = MyClass()
print(obj.x) # should output "Decorator applied" followed by "42"
但是打印给出:
<bound method my_decorator.<locals>.wrapper of <__main__.MyClass object at 0x7e0b7943ebf0>>
与我的真实场景相比,这已经是一个最小的例子了,我的装饰器要复杂得多,而且我有多个装饰器。
@property
装饰器基于描述符协议。当定义同名的类属性并提供 __get__
方法时,Python 解释器以特殊方式处理属性查找。详情请参阅参考资料。
一旦理解了描述符协议,您就可以通过查看它的实现来理解
@property
装饰器是如何工作的。实际的实现是用 C 语言实现的,但是参考和源代码包含纯 Python 等价物。我将废弃后者的一些部分。
class property(object):
def __init__(self, fget=None, ...):
...
self.__get = fget
...
def __get__(self, inst, type=None):
...
return self.__get(inst)
以下是
@property
装饰器的简单示例。
class X:
def __init__(self, a):
self.a = a
@property
def b(self):
return self.a * 10
x = X(1)
print(x.b) # This will output 10.
属性
b
的定义等价于以下。 (这是通用装饰器语法的简单应用。)
def get_b(self):
return self.a * 10
b = property(get_b)
当Python解释器处理属性查找
x.b
时,它识别出b
中存在类属性X
,并且该属性提供了__get__
方法,解释器调用该方法。在 __get__
方法内部,调用 get_b
调用的参数 property
方法。
一旦了解了
@property
的实现,您就可以通过定义新属性来使用装饰器包装属性,如以下示例所示。
def decorator_on_prop(prop):
def new_fget(self):
return prop.fget(self) + 1
return property(new_fget)
class X:
def __init__(self, a):
self.a = a
@decorator_on_prop
@property
def b(self):
return self.a * 10
x = X(1)
print(x.b) # This will output 11.