在我的代码中,我对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))
让我们运行它:
$ PYTHONPATH=~/test python3 e/m2.py
41536520 42656096
41537464 42656488
显然,平等(通过Enum
的身份)并不成立。那里的其他人都觉得这个麻烦吗?
让我详细说明一下。再添加两个文件:
$ cat e/file1.py
from m1 import E
class C():
def __init__(self):
self.x = E.x
还有一个。注意进口的差异。
$ 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)
两者都是有效的进口产品。现在运行它。
$ PYTHONPATH=~/test python3 e/file2.py
E.x E.x
Surprise! -> False
如何避免这个陷阱?我不应该为此感到困扰吗?
答案 0 :(得分:6)
后来,更快的是,我意识到自上次工作以来唯一的变化是
import
语句:使用显式模块路径而不是相对路径。
Python 3没有隐式相对导入。您的“相对”导入实际上是另一个绝对导入。您正在导入两个完全不同的模块m1
和e.m1
,这些模块碰巧来自同一个文件。
如果要在Python 3中使用相对导入,则需要明确说明:
from .m1 import E
# ^ explicit relative import
如果您将程序作为
运行python3 -m e.m2
您将避免模块搜索路径中存在允许m1
和e.m1
存在的问题。您也可以手动修复sys.path
并从e/m2.py
设置__package__
。
答案 1 :(得分:4)
这不是Enum
的问题,而是python导入。如果导入具有不同名称的同一模块,则会获得两个不同的模块。
尝试使用E1 is E2
。