重新加载模块后枚举比较变为假

Enum comparison become False after reloading module

我有 MyEnum,一个从 enum 派生的枚举,在 myenum.py 文件中定义,例如:

# myenum.py
import enum

class MyEnum(enum.Enum):
    ONE = 1
    TWO = 2

然后,我使用 importlib.import_module() 方法导入这个文件。我创建了 a 我的枚举实例,并测试它的值:它是正确的,符合预期。

但是,如果我重新加载我的文件,使用 importlib.reload()a 不再等于 MyEnum.ONE。是什么原因造成的?我在 Python 3.7.

# test.py
import importlib

def test_enum(e):
    print(e, myenum.MyEnum.ONE)
    print("test is :", e==myenum.MyEnum.ONE)

if __name__=='__main__':
    globals()["myenum"] = importlib.import_module("myenum")
    a = myenum.MyEnum.ONE
    test_enum(a)
    importlib.reload(globals()["myenum"])
    test_enum(a)

结果

MyEnum.ONE MyEnum.ONE
test is : True
MyEnum.ONE MyEnum.ONE
test is : False

编辑:经过进一步研究,Python 中的枚举似乎是按 ID 进行比较的。但是,当重新导入模块时,我的枚举的 ID 发生了变化,这就是比较 returns False.

的原因

有哪些选项可以避免此 ID 更改 允许比较保持 True?

  1. 换ID是避免不了的;你用新实例 创建了一个新的 class,而现有 class 的实例仍然存在 ;从定义上讲,ID 不允许相等。

  2. 如果你必须允许它们比较相等,尽管身份不同,你可以只覆盖enum上的__eq__来做随心所欲,例如:

    class MyEnum(enum.Enum):
        ONE = 1
        TWO = 2
        def __eq__(self, other):
            if type(self).__qualname__ != type(other).__qualname__:
                return NotImplemented
            return self.name == other.name and self.value == other.value
    
        def __hash__(self):
            return hash((type(self).__qualname__, self.name))
    

    我不推荐这个(正确使用 enums 将使用 is 进行比较,没有什么可以使它起作用,因为它依赖于 ID,每点 #1 ,将 总是 不同),并且它会 很多 慢(删除 enums 的好处之一),但它是如果在开发过程中必须允许 reloading,则可行。只需确保删除生产代码的 reload

您不能保证 MyEnum 将始终指代同一个 class。但是实例 e 本身总是引用同一个 class。因此,解决方法是将您的测试更改为:

print("test is :", e==type(e).ONE)