[英]Python: Circular dependency of dataclasses / Forward variable declaration?
所以,我在一個文件中有這兩個數據類:
@dataclass
class A:
children: List[B]
@dataclass
class B:
parent: A
,這可以通過使用__future__.annotations
特性來實現。
然后我有另外兩個文件,每個文件都有一堆針對我的項目的每種類型的對象,這些對象是 static。
文件objects_A
:
import objects_B
obj_a1 = A(
children=[
objects_B.obj_b1,
objects_B.obj_b2
]
)
文件objects_B
:
import objects_A
obj_b1 = B(
parent=objects_A.obj_a1
)
obj_b2 = B(
parent=objects_A.obj_a1
)
顯然,文件之間存在循環依賴問題,但即使它們在同一個文件中也不行,因為一種類型的變量依賴於另一種類型的變量才能成功。
初始化obj_a1
中的B
對象也不起作用,因為這里沒有self
的概念。
目前,我將parent
設置為None
(反對類型提示),然后在obj_a1
上循環以設置它們:
for obj_b in obj_a1.children:
obj_b.parent = obj_a1
伙計們有什么好主意嗎?
不知道它是否有幫助,但這些對象是 static(它們在這些聲明后不會改變)並且它們具有某種父子關系(正如您肯定已經注意到的那樣)。
如果可能的話,我希望將每種類型的變量放在不同的文件中。
我知道我遲到了,但我會在這里留下我的答案供其他人使用。
根據PEP 563 ,python 3.7 引入了注釋的惰性求值,這在循環依賴的情況下非常有用。
@dataclass
class StudentData:
school: 'SchoolData'
@dataclass
class SchoolData:
students: StudentData
如您所見, SchoolData
類型注釋包含在引號內,這樣您就可以在聲明之前引用SchoolData
類型。
解決此問題的一種方法是使用基礎 class 作為前向聲明的替代方案。
@dataclass
class ParentBase:
children: List[object]
@dataclass
class Child:
parent: ParentBase
@dataclass
class Parent(ParentBase):
children: List[Child]
parent = Parent(children=[])
child = Child(parent=parent)
parent.children.append(child)
這將起作用。 我在ParentBase
添加了children: List[object]
。 這不是此代碼工作所必需的,但如果您添加它,您的 IDE 可以在您開始訪問child.parent.
.
這不會阻止任何人使用ParentBase
實例化Child
。 要解決該問題,您可以執行以下操作:
@dataclass
class ParentBase(abc.ABC):
children: List[object]
@abc.abstractmethod
def __post_init__(self):
pass
@dataclass
class Child:
parent: ParentBase
@dataclass
class Parent(ParentBase):
children: List[Child]
def __post_init__(self):
pass
parent = Parent(children=[])
child = Child(parent=ParentBase()) # TypeError
child = Child(parent=parent)
parent.children.append(child)
它可能過於防御和過多的樣板代碼。 是否要使其更安全取決於您團隊的偏好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.