【问题标题】:How to construct circular referencing instances of a frozen class in python如何在python中构造冻结类的循环引用实例
【发布时间】:2021-10-01 19:54:10
【问题描述】:

我有一个相互引用的数据类实例。

from dataclasses import dataclass

@dataclass()
class Foo:
    id: int
    neighbor: 'Foo'
        
foo = Foo(1, None)
bar = Foo(2, foo)
foo.neighbor = bar

我真的想要一个冻结类,因为不能在多线程运行中操作这些对象。但是如果我声明frozen=True,最后一行显然会引发错误。我想不出办法来处理这个问题。我阅读了this thread,但该解决方案对我不起作用,因为foo.neighbor 应该指向另一个冻结的实例。

有什么方法可以实现吗?我不受数据类的约束。但是我在使用命名元组时遇到了同样的问题。

【问题讨论】:

    标签: python self-reference namedtuple python-dataclasses


    【解决方案1】:

    frozen 通过覆盖__setattr__ 工作。您可以通过直接访问实例的__dict__ 属性来完全绕过__setattr__

    foo.__dict__['neighbor'] = bar
    

    我不知道这是否会产生任何意想不到的副作用(如果您使用__slots__ 来阻止创建__dict__,肯定不会起作用),但它可能足以满足您的用例.

    (如果实现更改为使用 C 扩展而不是当前动态生成源代码以传递给 exec 的方法,这在 dataclass 的未来版本中也可能失败。namedtuple 沿着这些方向发展,我相信。)


    或者,您可以使用 dataclasses 本身用于初始化冻结类的属性的相同技巧:显式使用 object.__setattr__

    object.__setattr__(foo, 'neighbor', bar)
    

    【讨论】:

    • 令人惊讶的流动冻结课程毕竟如此。
    • 文档明确指出您不能在 Python 中创建真正的只读对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    相关资源
    最近更新 更多