Python 3 會搜尋所有的 sys.path 的 root path. 因此在 Python2 中用不同的 import path 會導致同一個 module 互不相等的現象在 Python 3 中不會發生. PEP 328 | Issue30545
舉例來說:
File content and structure
1
2
3
4
5
| /test_enum
- /test_enum/__init__.py
module_a.py
module_b.py
the_enum.py
|
the_enum.py
1
2
3
4
5
6
7
| from enum import Enum
class Fruit(Enum):
APPLE = 'apple'
BANANA = 'banana'
GUAVA = 'guava'
PINEAPPLE = 'pineapple'
|
module_a.py
1
2
3
| from . import module_b
from . import the_enum
from .the_enum import Fruit
|
module_b.py
Python2 vs Python3
1
2
3
4
5
6
7
8
9
10
| from enum_test import module_a, module_b, the_enum
# 同樣 import the_enum, 然後從它存取 Fruit
print(module_a.the_enum.Fruit.APPLE == module_b.the_enum.Fruit.APPLE)
# Python2: True, Python3:True
# 不同 import path
print(module_a.Fruit.APPLE == module_b.the_enum.Fruit.APPLE)
# Python2: False, Python3:True
|
參考
雖然 Python2 中不同 import path 導致物件不相等(id 不同), 但是他們的值是相同的, 所以 hash 這兩個不同 id 的物件會得到相同的 hash value, implement __eq__ 來比較 hash values 就可以得到正確的比較結果.
Customized equal.
1
2
3
4
5
6
7
8
9
10
11
| from enum import Enum
class Fruit(Enum):
APPLE = 'apple'
BANANA = 'banana'
GUAVA = 'guava'
PINEAPPLE = 'pineapple'
def __eq__(self, other):
return hash(self) == hash(other)
|
Result
1
2
3
4
5
6
7
8
9
| from enum_test import module_a, module_b, the_enum
print(module_a.the_enum.Fruit.APPLE == module_b.the_enum.Fruit.APPLE)
# Python2: True, Python3:True
# 雖然兩個 enum 還是因為不同的 path 而不相等, 但是 __eq__ 使用 member 的 hash 值比較, 所以還是相等.
print(module_a.Fruit.APPLE == module_b.the_enum.Fruit.APPLE)
# Python2: True, Python3:True
|