如何避免 Python 中的循环导入而不合并到单个文件中

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

这是我的文件:

- ./
    - child.py
    - parent.py
    - main.py

child.py

from dataclasses import dataclass
from parent import Parent

@dataclass
class Child:
    name: str

    def get_mother(self) -> Parent:
        # simulating query from database...
        return Parent(
            name="Jane",
            children=[
                Child(self.name),
                Child("Alice"),
                Child("Bob"),
            ],
        )

parent.py

from dataclasses import dataclass

from child import Child


@dataclass
class Parent:
    name: str
    children: list[Child]

main.py

from dataclasses import dataclass

from child import Child

if __name__ == "__main__":
    Charles = Child("Charles")
    print(f"{Charles}'s mother is {Charles.get_mother()}")

问题

如何在不合并 2 个文件的情况下解决此循环导入问题。

运行

main.py
引发异常

python main.py

Traceback (most recent call last):
  File "d:\circular_import\main.py", line 3, in <module>
    from child import Child

然后,我将所有 3 个文件中的

from xx import XX
更改为
import xx
。但是,这并不能解决问题。

python main.py

Traceback (most recent call last):
  File "d:\circular_import\main.py", line 3, in <module>
    import child
  File "d:\circular_import\child.py", line 3, in <module>
    import parent
  File "d:\circular_import\parent.py", line 7, in <module>
    class Parent:
  File "d:\circular_import\parent.py", line 9, in Parent
    children: list[child.Child]
AttributeError: partially initialized module 'child' has no attribute 'Child' (most likely due to a circular import)

如果我将

parents.py
child.py
合并到一个文件中,它确实可以解决问题。但这是一个不太理想的解决方案。

python main.py

Child(name='Charles')'s mother is Parent(name='Jane', children=[Child(name='Charles'), Child(name='Alice'), Child(name='Bob')])
python python-3.x python-import circular-dependency
2个回答
0
投票

这已经回答了

这个想法是从方法内部延迟导入之一。 但这需要放宽一些类型声明。

    def get_mother(self):
        from parent import Parent
        # simulating query from database...
        return Parent(
            name="Jane",
            children=[
                Child(self.name),
                Child("Alice"),
                Child("Bob"),
            ],
        )

0
投票

由于您仅将它们用于类型提示,因此您只需在类型检查时导入它们。

from dataclasses import dataclass
import typing
if typing.TYPE_CHECKING:
    from child import Child

@dataclass
class Parent:
    name: str
    children: "list[Child]"

这不会在运行时创建循环导入,但仍然可以正确键入提示。

子级对父级有“真正”的依赖,因此需要正常导入

© www.soinside.com 2019 - 2024. All rights reserved.