我知道 Python 中的循环导入问题之前已经出现过很多次,我也读过这些讨论。这些讨论中反复出现的评论是,循环导入是糟糕设计的标志,应该重新组织代码以避免循环导入。
有人能告诉我在这种情况下如何避免循环导入吗?:我有两个类,我希望每个类都有一个构造函数(方法),它接受另一个类的实例并返回该类的实例。
更具体地说,一个类是可变的,另一个是不可变的。不可变类用于哈希、比较等。可变类也用于执行操作。这类似于集合和冻结集或列表和元组。
我可以将两个类定义放在同一个模块中。还有其他建议吗?
一个玩具示例是类 A,它有一个属性,即列表;类 B,它有一个属性,即元组。然后类 A 有一个方法,它接受类 B 的一个实例并返回类 A 的一个实例(通过将元组转换为列表);同样,类 B 有一个方法,它接受类 A 的一个实例并返回类 B 的一个实例(通过将列表转换为元组)。
要避免 Python 中的循环导入问题,尤其是在两个类相互依赖时,可以使用以下几种策略来重构和设计代码。下面是几个可行的方法,适合你的情况:
如果两个类密切相关,将它们放在同一个模块中是一个简单有效的解决方案。这种方式避免了导入循环问题,因为两个类定义在同一个文件中。
# mymodule.py class A: def __init__(self, items): self.items = items def to_list(self): return self.items def convert_from_b(self, b_instance): return A(list(b_instance.items)) class B: def __init__(self, items): self.items = items def to_tuple(self): return tuple(self.items) def convert_from_a(self, a_instance): return B(tuple(a_instance.items))
如果你希望将两个类保留在不同的模块中,可以在需要时进行局部导入,以避免循环导入问题。
文件: a.py
a.py
class A: def __init__(self, items): self.items = items def convert_from_b(self, b_instance): from b import B # 局部导入 return A(list(b_instance.items))
文件: b.py
b.py
class B: def __init__(self, items): self.items = items def convert_from_a(self, a_instance): from a import A # 局部导入 return B(tuple(a_instance.items))
将公共逻辑或共享功能提取到一个独立的模块中,这样可以打破类之间的直接依赖关系,避免循环导入问题。
文件: common.py
common.py
def list_to_tuple(lst): return tuple(lst) def tuple_to_list(tpl): return list(tpl)
from common import tuple_to_list class A: def __init__(self, items): self.items = items def convert_from_b(self, b_instance): return A(tuple_to_list(b_instance.items))
from common import list_to_tuple class B: def __init__(self, items): self.items = items def convert_from_a(self, a_instance): return B(list_to_tuple(a_instance.items))
如果你使用的是 Python 3.7 及以上版本,可以利用类型注解和 TYPE_CHECKING 进行延迟导入。这可以帮助在类型检查时解决依赖问题,而在实际运行时避免导入循环。
TYPE_CHECKING
from typing import TYPE_CHECKING if TYPE_CHECKING: from b import B class A: def __init__(self, items): self.items = items def convert_from_b(self, b_instance: 'B') -> 'A': from b import B # 局部导入用于避免循环 return A(list(b_instance.items))
from typing import TYPE_CHECKING if TYPE_CHECKING: from a import A class B: def __init__(self, items): self.items = items def convert_from_a(self, a_instance: 'A') -> 'B': from a import A # 局部导入用于避免循环 return B(tuple(a_instance.items))
选择最适合你项目的方案,根据代码的复杂性和结构来决定最佳的设计方式。