【问题标题】:Enum comparison become False after reloading module重新加载模块后枚举比较变为 False
【发布时间】:2021-03-03 14:18:17
【问题描述】:

我有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 发生了变化,这就是比较返回 False 的原因。

有哪些选项可以避免这种 ID 更改允许比较保持为真?

【问题讨论】:

  • 如果你的枚举值只是整数,那么我建议使用IntEnum,它允许按值而不是身份进行比较
  • @GeorgeD。不。这违背了枚举的全部目的
  • 请注意,即使它们没有在您重新加载模块后通过 id 进行比较,您实际上也有两个单独的类型,并且大多数类型在相等比较中考虑类型本身,例如if isinstance(other, Foo): return self.value == other.value else return NotImplemented。所以这总是会有问题的

标签: python python-importlib


【解决方案1】:
  1. ID 变更无法避免;你用新实例创建了一个新类而现有类的实例仍然存在;从定义上讲,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

【讨论】:

  • 确实,没有干净的方法来解决这个问题。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 2023-03-09
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多