In my code, I was puzzled by Enum
instances with the same value not comparing equal. I quickly realized that their id(...)
were different. Later, much less quickly, I realized that the only change since it last worked was the import
statement: using explicit module path rather than relative.
Then I came up with this isolated example.
$ 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))
Let's run it:
$ PYTHONPATH=~/test python3 e/m2.py
41536520 42656096
41537464 42656488
Obviously, equality (which is by identity for Enum
) does not hold. Anyone else out there find this troubling?
Let me elaborate. Adding two more files:
$ cat e/file1.py
from m1 import E
class C():
def __init__(self):
self.x = E.x
One more. Note the difference in imports.
$ 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)
Both are valid imports. Now run it.
$ PYTHONPATH=~/test python3 e/file2.py
E.x E.x
Surprise! -> False
How can I avoid this trap? Is there a reason why I should not be troubled by this?
equals method uses == operator internally to check if two enum are equal. This means, You can compare Enum using both == and equals method.
Introduction to the enum aliases By definition, the enumeration member values are unique. However, you can create different member names with the same values.
The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden). An enum cannot be used to create objects, and it cannot extend other classes (but it can implement interfaces).
Later, much less quickly, I realized that the only change since it last worked was the
import
statement: using explicit module path rather than relative.
Python 3 doesn't have implicit relative imports. Your "relative" import is actually another absolute import. You're importing two completely distinct modules, m1
and e.m1
, that happen to come from the same file.
If you want to use a relative import in Python 3, you need to make it explicit:
from .m1 import E
# ^ explicit relative import
If you run the program as
python3 -m e.m2
you'll avoid the problems with the module search path that allowed both m1
and e.m1
to exist. You can also manually fix sys.path
and set __package__
from e/m2.py
.
This is not an issue with Enum
, but with python imports. If you import the same module with a different name, you get two different modules.
Try, for example, E1 is E2
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With