当两个项目彼此作为字段时出现递归错误

RecursionError when two items have each other as a field

我正在研究数据类,发现循环属性在使用 asdict 等表示方法时会导致问题。在下面的示例中,我们创建了两个 Word 并将它们放在彼此的 linked_word 字段中。当我们试图用其中一个词创建字典时,这将导致递归错误,因为它们的属性不断地相互引用。但是,我不确定如何处理。

from __future__ import annotations
import dataclasses
from typing import Optional


@dataclasses.dataclass
class Word:
    text: str
    linked_word: Optional[Word] = None

hello = Word("hello")
world = Word("world")

hello.linked_word = world
world.linked_word = hello

print(dataclasses.asdict(world))  # will throw RecursionError

我不确定这个问题是否是 dataclassesasdictastuple)中的表示函数所特有的,或者这是否只是作为一个整体“不允许”在数据类中(我不这么认为)。

然后,主要目标是能够以 包含违规属性的方式使用 asdict(完全避免错误) ,或者能够覆盖 asdict 方法,以便我可以向我的用户提供更好的错误消息,说明此对象不能在 asdict.

中使用

递归错误是正常的,因为您给出的 parent 与 child 相同。如果您使用相同的世界 class 作为 2 顺序 child 结果将进入无限递归。你需要改变你的child class,你可以看看类似的解决方案;

from __future__ import annotations
import dataclasses
from typing import Optional


@dataclasses.dataclass
class Word:
    text: str
    linked_word: Optional[Word] = None

hello = Word("hello")
world = Word("world")
obbs = Word("obstacle")

hello.linked_word = world
#world.linked_word = hello # its normal to give recursion error because 
                           # you give same class (world) as a child
obbs.linked_word = hello

print(dataclasses.asdict(obbs))  # will NOT throw RecursionError

结果: {'text': 'obstacle', 'linked_word': {'text': 'hello', 'linked_word': {'text': 'world', 'linked_word': None}}}

如果我们回到问题的主要目标,您可以编写一个预检查代码来防止递归,在继承之前检查 data-class 的所有 child :)

希望对你有用, 问候