如何修改软件架构以解决循环导入?
How to modify software architecture in order to resolve circular import?
我目前正在编写一些用于人口模型模拟的 Python 2.7 代码,我遇到了循环导入的问题。
模型结构如下:
Island
class(在landscape.py
)
- 具有坐标的景观单元集合
Cell
class(在landscape.py
)
- 超级class 适用于所有景观单元格(
Jungle
、Savannah
、Mountain
等)。单元格 class 有一个包含该单元格中不同动物的字典。
animal
字典的结构如下:
animals = {AnimalType1: [animal1_inst_1, animal_2_inst_2],
AnimalType2: [animal2_inst_1, animal_2_inst_2]}
每个单元格的初始 animal
字典设置在 运行 时间。
Animal
class(在animals.py
)
- 对所有动物类型超级class(目前只有
Herbivore
和Carnivore
)。
所有动物 classes 都有一个 class 变量,allowed_cells
,这是该动物可以居住的所有细胞类型的列表,例如
allowed_cells = [landscape.Jungle, landscape.Savannah]
我的问题是 - animals.py 导入 landscape.py 以检查动物字典中的所有键是否都是 Animal
subclasses 以及是否所有实例都在相应的列表是该动物的实例 class。在 animals.py
中,导入 landscape.py
以便 allowed_cells
列表可以包含实际单元格 classes,此外还有其他地方的许多测试。
当我尝试 运行 代码时,出现错误:
Traceback (most recent call last):
File "C:/Users/yngve_000/Documents/INF200/inf200_dag_yngve/PA04/biosim/simulation.py", line 10, in <module>
import landscape as landscape
File "C:\Users\yngve_000\Documents\INF200\inf200_dag_yngve\PA04\biosim\landscape.py", line 12, in <module>
import animals
File "C:\Users\yngve_000\Documents\INF200\inf200_dag_yngve\PA04\biosim\animals.py", line 18, in <module>
class Animal(object):
File "C:\Users\yngve_000\Documents\INF200\inf200_dag_yngve\PA04\biosim\animals.py", line 70, in Animal
allowed_cell_types = [landscape.Jungle, landscape.Desert,
AttributeError: 'module' object has no attribute 'Jungle'
我明白为什么会出现这个错误,但不知道如何以优雅的方式消除它。可以为 Animal class 创建一个 is_animal 函数并使用 try/except 的一些变通方法,但至少可以说这似乎很麻烦。
最好的解决方法是什么?
animals
导入 landscape
以定义动物可以居住的地方似乎很自然。另一方面,我不明白为什么 landscape
中需要 Animal
s。一个单元格可以(可能)在没有任何 Animal
的情况下存在,但每个 Animal
都必须存在于一个单元格中。所以你应该尝试从 landscape
中删除动物的东西,这个模块应该只包含景观 类。实例化应该发生在不同的模块中,并且单元格应该在实例化时填充动物。因此,使动物列表成为 __init__
.
的参数
请注意,您可以通过子类检查执行 is_animal
形式的检查。 IE。如果 Dog
继承自 Animal
,则 issubclass(Dog, Animal)
的计算结果为 True
。你也可以使用 abstract base classes to register other 类 as sub类.
尝试在 landscape.py
内部导入 Animal
,而不是在文件开头,而是在本地,在检查键 类 的函数 中].
实际上,这是一种常见的方法——当你面临循环导入时,使用本地导入。但要小心 — 循环导入通常表明您的代码在耦合方面存在问题。
我目前正在编写一些用于人口模型模拟的 Python 2.7 代码,我遇到了循环导入的问题。
模型结构如下:
Island
class(在landscape.py
)
- 具有坐标的景观单元集合
Cell
class(在landscape.py
)
- 超级class 适用于所有景观单元格(
Jungle
、Savannah
、Mountain
等)。单元格 class 有一个包含该单元格中不同动物的字典。 animal
字典的结构如下:animals = {AnimalType1: [animal1_inst_1, animal_2_inst_2], AnimalType2: [animal2_inst_1, animal_2_inst_2]}
每个单元格的初始
animal
字典设置在 运行 时间。
Animal
class(在animals.py
)
- 对所有动物类型超级class(目前只有
Herbivore
和Carnivore
)。 所有动物 classes 都有一个 class 变量,
allowed_cells
,这是该动物可以居住的所有细胞类型的列表,例如allowed_cells = [landscape.Jungle, landscape.Savannah]
我的问题是 - animals.py 导入 landscape.py 以检查动物字典中的所有键是否都是 Animal
subclasses 以及是否所有实例都在相应的列表是该动物的实例 class。在 animals.py
中,导入 landscape.py
以便 allowed_cells
列表可以包含实际单元格 classes,此外还有其他地方的许多测试。
当我尝试 运行 代码时,出现错误:
Traceback (most recent call last):
File "C:/Users/yngve_000/Documents/INF200/inf200_dag_yngve/PA04/biosim/simulation.py", line 10, in <module>
import landscape as landscape
File "C:\Users\yngve_000\Documents\INF200\inf200_dag_yngve\PA04\biosim\landscape.py", line 12, in <module>
import animals
File "C:\Users\yngve_000\Documents\INF200\inf200_dag_yngve\PA04\biosim\animals.py", line 18, in <module>
class Animal(object):
File "C:\Users\yngve_000\Documents\INF200\inf200_dag_yngve\PA04\biosim\animals.py", line 70, in Animal
allowed_cell_types = [landscape.Jungle, landscape.Desert,
AttributeError: 'module' object has no attribute 'Jungle'
我明白为什么会出现这个错误,但不知道如何以优雅的方式消除它。可以为 Animal class 创建一个 is_animal 函数并使用 try/except 的一些变通方法,但至少可以说这似乎很麻烦。
最好的解决方法是什么?
animals
导入 landscape
以定义动物可以居住的地方似乎很自然。另一方面,我不明白为什么 landscape
中需要 Animal
s。一个单元格可以(可能)在没有任何 Animal
的情况下存在,但每个 Animal
都必须存在于一个单元格中。所以你应该尝试从 landscape
中删除动物的东西,这个模块应该只包含景观 类。实例化应该发生在不同的模块中,并且单元格应该在实例化时填充动物。因此,使动物列表成为 __init__
.
请注意,您可以通过子类检查执行 is_animal
形式的检查。 IE。如果 Dog
继承自 Animal
,则 issubclass(Dog, Animal)
的计算结果为 True
。你也可以使用 abstract base classes to register other 类 as sub类.
尝试在 landscape.py
内部导入 Animal
,而不是在文件开头,而是在本地,在检查键 类 的函数 中].
实际上,这是一种常见的方法——当你面临循环导入时,使用本地导入。但要小心 — 循环导入通常表明您的代码在耦合方面存在问题。