重新加载模块后枚举比较变为假
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?
换ID是避免不了的;你用新实例 创建了一个新的 class,而现有 class 的实例仍然存在 ;从定义上讲,ID 不允许相等。
如果你必须允许它们比较相等,尽管身份不同,你可以只覆盖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))
我不推荐这个(正确使用 enum
s 将使用 is
进行比较,没有什么可以使它起作用,因为它依赖于 ID,每点 #1 ,将 总是 不同),并且它会 很多 慢(删除 enum
s 的好处之一),但它是如果在开发过程中必须允许 reload
ing,则可行。只需确保删除生产代码的 reload
。
您不能保证 MyEnum
将始终指代同一个 class。但是实例 e
本身总是引用同一个 class。因此,解决方法是将您的测试更改为:
print("test is :", e==type(e).ONE)
我有 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?
换ID是避免不了的;你用新实例 创建了一个新的 class,而现有 class 的实例仍然存在 ;从定义上讲,ID 不允许相等。
如果你必须允许它们比较相等,尽管身份不同,你可以只覆盖
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))
我不推荐这个(正确使用
enum
s 将使用is
进行比较,没有什么可以使它起作用,因为它依赖于 ID,每点 #1 ,将 总是 不同),并且它会 很多 慢(删除enum
s 的好处之一),但它是如果在开发过程中必须允许reload
ing,则可行。只需确保删除生产代码的reload
。
您不能保证 MyEnum
将始终指代同一个 class。但是实例 e
本身总是引用同一个 class。因此,解决方法是将您的测试更改为:
print("test is :", e==type(e).ONE)