我有一个如下所示的设置

class decorator:
    def __init__(self, fn):
        self.fn = fn

    @staticmethod
    def wrap(fn):
        return decorator(fn)

    def __call__(self):
        print(f"decorator {self} function called")


class A:
    @decorator.wrap
    def foo(self):
        print(f"Object {self} called")

    def __init__(self):
        self.boo = 'Boo'

我如何从decorator 对象访问boo变量?

推荐答案

@S.B的解决方案有效,但不是线程安全的,因为A的多个实例可能在不同的线程中几乎同时调用foo方法,在从另一个实例调用__call__方法之前覆盖修饰符对象的instance属性.

一种线程安全的方法是从__get__方法返回一个包装器函数,并通过闭包获得该实例:

class decorator:
    def __init__(self, fn):
        self.fn = fn

    def __get__(self, instance, owner=None):
        def wrapper(*args, **kwargs):
            print(f'decorator {self} function called; boo = {instance.boo}')
            return self.fn(instance, *args, **kwargs)
        return wrapper

class A:
    @decorator
    def foo(self):
        print(f"Object {self} called")

    def __init__(self):
        self.boo = 'Boo'

A().foo()

这会产生以下结果:

decorator <__main__.decorator object at 0x7f6ef3316c10> function called; boo = Boo
Object <__main__.A object at 0x7f6ef3339580> called

演示:Try it online!

Python相关问答推荐

是否有使用纯霍夫曼编码的现代图像格式?

双情节在单个图上切换-pPython

Plotly Dash函数来切换图形参数-pPython

为什么我的(工作)代码(生成交互式情节)在将其放入函数中时不再工作?

如何将Matplotlib的fig.add_axes本地坐标与我的坐标关联起来?

为什么dict(id=1,**{id:2})有时会引发KeyMessage:id而不是TypMessage?

Pydantic:如何将对象列表表示为dict(将列表序列化为dict)

DuckDB将蜂巢分区插入拼花文件

Python会扔掉未使用的表情吗?

海运图:调整行和列标签

ODE集成中如何终止solve_ivp的无限运行

如何使用pytest来查看Python中是否存在class attribution属性?

运输问题分支定界法&

梯度下降:简化要素集的运行时间比原始要素集长

为一个组的每个子组绘制,

pandas在第1列的id,第2列的标题,第3列的值,第3列的值?

使用Python从URL下载Excel文件

处理具有多个独立头的CSV文件

如何检测鼠标/键盘的空闲时间,而不是其他输入设备?

Python—压缩叶 map html作为邮箱附件并通过sendgrid发送