在Python中已经用@property装饰的方法上应用装饰器

问题描述 投票:0回答:1

为什么当 @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>>

与我的真实场景相比,这已经是一个最小的例子了,我的装饰器要复杂得多,而且我有多个装饰器。

python python-decorators
1个回答
0
投票

@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.
© www.soinside.com 2019 - 2024. All rights reserved.