【问题标题】:Python Enums across Modules跨模块的 Python 枚举
【发布时间】:2014-10-27 14:29:46
【问题描述】:

如果枚举已在主模块中定义,为什么不能在 Python 3 中跨模块边界正确检查枚举相等性?这是一个例子:

模块A.py:

#!/usr/bin/python3

import moduleB
from enum import Enum, unique

@unique
class MyEnum(Enum):
    A = 1
    B = 2
    # def __eq__(self,other):
    #     assert isinstance(other,self.__class__)
    #     return self.value == other.value

if __name__ == "__main__":

    myVar = MyEnum.B
    moduleB.doStuff(myVar)

模块B.py:

#!/usr/bin/python3

import moduleA

def doStuff(aVariable):
    bVariable = moduleA.MyEnum.B
    assert aVariable == bVariable

在命令行上调用“./moduleA.py”会产生:

Traceback (most recent call last):
  File "./moduleA.py", line 17, in <module>
    moduleB.doStuff(myVar)
  File "/home/ruedi/Dropbox/Reps/stuffed/sosy/testing/moduleB.py", line 7, in doStuff
    assert aVariable == bVariable
AssertionError

取消注释枚举中的自定义相等运算符会导致断言失败。我发现类模块在两种情况下都不相同,因为在一种情况下它是“__main__”。

解决此问题的最“Pythonic 方式”是什么(除了将枚举移至其自己的模块)?

编辑:切换到“aVariable is bVariable”也不起作用:

Traceback (most recent call last):
  File "./moduleA.py", line 17, in <module>
    moduleB.doStuff(myVar)
  File "/home/ruedi/Dropbox/Reps/stuffed/sosy/testing/moduleB.py", line 7, in doStuff
    assert aVariable is bVariable
AssertionError

【问题讨论】:

    标签: python module enums


    【解决方案1】:

    就 Python 而言,这里有 三个 模块:

    • __main__
    • moduleA
    • moduleB

    您从命令行运行的文件,主入口点,始终存储为__main__ 模块。如果您在代码中的任何位置导入moduleA,Python 会将其与__main__ 模块分开,并创建一个新的模块对象。因此,您有 两个 单独的 MyEnum 类:

    • __main__.MyEnum
    • moduleA.MyEnum

    他们的成员是不同的,因此不能相等。

    如果您使用import __main__ as moduleA 而不是使用import moduleA,或者使用单独的 脚本文件来驱动测试,则您的测试通过;那个单独的文件会变成__main__:

    #!/usr/bin/python3
    # test.py, separate from moduleA.py and moduleB.py
    
    import moduleA    
    import moduleB
    
    if __name__ == "__main__":
        myVar = moduleA.MyEnum.B
        moduleB.doStuff(myVar)
    

    另一种解决方法是告诉 Python __main__ 和 moduleA 是同一个东西; 在导入moduleA(或moduleB,导入moduleA)之前,您可以向sys.modules 添加另一个条目:

    if __name__ == '__main__':
        import sys
        sys.modules['moduleA'] = sys.modules['__main__']
    
    import moduleB
    

    我认为这不是 Pythonic。

    【讨论】:

    • 它是否有充分的理由以这种方式工作,为什么要区分__main__ 和moduleA?你不希望它们是一样的吗?
    • @TankorSmash:它们是分开的,因为您需要一种方法来区分主入口点(脚本)和您导入的模块。这就是为什么 if __name__ == '__main__': 首先起作用的原因。
    猜你喜欢
    • 2023-03-16
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    相关资源
    最近更新 更多