Python 在不合并文件的情况下解决循环导入

Python Resolving Circular Imports without merging files

我有一段代码定义了游戏中可能的物品类型和附魔类型。某些附魔类型彼此不兼容或与某些物品类型不兼容。我希望每个项目类型都有关于哪些附魔与其不兼容的信息,以及每个附魔都包含与其兼容的项目的信息,而不必经常查找其中一个。

items.py:

from enum import Enum, auto

class ItemType(Enum):
  PLATE = auto()
  HELMET = auto()
  BOOTS = auto()
  SWORD = auto()
  BOW = auto()
# Get compatible enchantment types
from enchantments import EnchantmentType
for it in ItemType:
  it.compatible_enchantments = set(filter(lambda ench: it in ench.compatible_items, EnchantmentType))


class Item:
  def __init__(self, item_type, enchantments=None):
    self.type = item_type
    self.enchantments = []
    if enchantments:
      for ench in enchantments:
        self.add_enchantment(ench)

  def add_enchantment(self, enchantment, i=None):
    if enchantment.type not in self.compatible_enchantments:
      raise ValueError(f"Enchantment {enchantment.type} is incompatible with {self.type}.")
    if i is None:
      self.enchantments.append(enchantment)
    else:
      self.enchantments.insert(enchantment, i)    from enum import Enum
from items import ItemType as IT

enchantments.py:

from enum import Enum, auto

class EnchantmentType(Enum):
  ENHANCED_ARMOUR = IT.HELMET, IT.PLATE, IT.BOOTS, IT.RING
  ENHANCED_DAMAGE = IT.SWORD, IT.BOW, IT.RING
  YELLOW_COLOUR = ()

  def __init__(self, *compatible_item_types):
    self.compatible_items = set(IT) if not compatible_item_types else compatible_item_types
    self.incompatible_enchantments = set()
# Fill in the incompatible enchantments
for mutualy_exclusive_group in (
    {EnchantmentType.ENHANCED_ARMOUR, EnchantmentType.ENHANCED_DAMAGE}
):
  for ench in mutualy_exclusive_group:
    ench.incompatible_enchantments += mutualy_exclusive_group - {ench}


class Enchantment:
  def __init__(self, enchantment_type, level=None):
    self.type = enchantment_type
    self.level = level

main.py:

from enchantments import EnchantmentType as ET

print(ET.ENHANCED_ARMOUR.compatible_items)
print(ET.ENHANCED_DAMAGE.compatible_items)
print(ET.YELLOW_COLOUR.compatible_items)

Running this code 给我一个 ImportError 引用循环导入。

this answer 之后,我尝试将 from x import y 语句更改为 import x,但仍然出现相同的错误。

我通过从 items.py 中删除 from enchantments import EnchantmentType 并移动行

暂时解决了这个问题
from enchantments import EnchantmentType
for it in ItemType:
  it.compatible_enchantments = set(filter(lambda ench: it in ench.compatible_items, EnchantmentType))

变成enchantments.py。但是,这需要任何希望获得有关附魔的正确信息的模块手动导入 enchantments.py——仅导入 items.py 将导致所有 compatible_enchantments 为空。

有没有办法在不合并两个文件的情况下使我的循环导入工作?

为什么不在每个 ItemTypes 上设置 compatible_enchantments,为什么不在某个地方(可能在 enchantments.py 中)有一个字典将 EnchantmentType 映射到它可以应用的有效 ItemTypes 集?

对我来说,ItemType 似乎不需要了解附魔,而是附魔需要知道它们是否可以应用于特定的 ItemType。