导入的Enum类不是等于自身的比较

use*_*854 4 python enums python-3.x

在我的代码中,我对Enum具有相同值但不比较相等的实例感到困惑.我很快意识到他们id(...)的不同.后来,不那么快,我意识到自上次工作以来唯一的变化是import声明:使用显式模块路径而不是相对路径.

然后我想出了这个孤立的例子.

$ ls
e/

$ ls e
__init__.py  __pycache__/  m1.py  m1.pyc  m2.py

$  python3 --version
Python 3.5.1

$ cat e/m1.py
from enum import Enum
class E(Enum):
    x=0

$ cat e/m2.py
from m1 import E as E1
from e.m1 import E as E2

print(id(E1), id(E1.x))
print(id(E2), id(E2.x))
Run Code Online (Sandbox Code Playgroud)

我们来吧:

$ PYTHONPATH=~/test python3 e/m2.py
41536520 42656096
41537464 42656488
Run Code Online (Sandbox Code Playgroud)

显然,平等(由身份证明Enum)并不成立.那里的其他人都觉得这个麻烦吗?

让我详细说明一下.再添加两个文件:

$ cat e/file1.py
from m1 import E

class C():
    def __init__(self):
        self.x = E.x
Run Code Online (Sandbox Code Playgroud)

多一个.注意进口的差异.

$ cat e/file2.py
from e.m1 import E
from file1 import C

c = C()
print(c.x, E.x)
print('Surprise! ->', c.x is E.x)
Run Code Online (Sandbox Code Playgroud)

两者都是有效的进口.现在运行它.

$ PYTHONPATH=~/test python3 e/file2.py
E.x E.x
Surprise! -> False
Run Code Online (Sandbox Code Playgroud)

我怎样才能避免这个陷阱?我不应该为此感到困扰吗?

Eth*_*man 8

这不是 的问题Enum,而是 python 导入的问题。如果使用不同的名称导入相同的模块,则会得到两个不同的模块。

例如,尝试一下E1 is E2


use*_*ica 7

后来,不那么快,我意识到自上次工作以来唯一的变化是import声明:使用显式模块路径而不是相对路径.

Python 3没有隐式相对导入.您的"相对"导入实际上是另一种绝对导入.您正在导入两个完全不同的模块,m1e.m1这些模块恰好来自同一个文件.

如果要在Python 3中使用相对导入,则需要将其显式化:

from .m1 import E
#    ^ explicit relative import
Run Code Online (Sandbox Code Playgroud)

如果你运行该程序

python3 -m e.m2
Run Code Online (Sandbox Code Playgroud)

您将避免模块搜索路径中允许存在m1e.m1存在的问题.您也可以手动修复sys.path和设置__package__e/m2.py.