2016-11-02 2 views
3

제 코드에서 동일한 값이 같지 않은 인스턴스가 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 

어떻게이 트랩을 피할 수 있습니까? 이 일로 인해 고생해서는 안되는 이유가 있습니까?

답변

5

나중에 훨씬 더 빨리, 마지막으로 작업 한 이후의 유일한 변경은 import 문이었습니다. 상대 경로가 아닌 명시 적 모듈 경로 사용.

파이썬 3에는 암시 적 상대 가져 오기가 없습니다. 귀하의 "상대"수입은 실제로 또 다른 절대 수입입니다. 같은 파일에서 온 두 개의 전혀 다른 모듈 인 m1e.m1을 가져옵니다.

python3 -m e.m2 

당신이 가진 문제를 피할 수 있습니다으로

from .m1 import E 
# ^explicit relative import 

를이 프로그램을 실행하면 : 당신은 파이썬 3에서 상대 가져 오기를 사용하려면

, 당신은 명시 적으로 만들 필요가 m1e.m1을 모두 허용하는 모듈 검색 경로 sys.path을 직접 수정하고 __package__e/m2.py으로 설정할 수도 있습니다.

+0

'import sys; print ('\ n'.join (sorted (sys.modules)))'는 실제로'm1'과'e.m1' 모듈을 보여줍니다. 하지만 저를 어떻게 생각 하느냐는 파이썬이 처음에'm1'을 발견 한 방법입니다. 필자는 암묵적인 상대 import가 python 3.3 이후로 허용되지 않는다고 생각했다. – tdelaney

+0

@tdelaney : 절대 가져 오기이며 상대 가져 오기는 아닙니다. 'e' 디렉토리와 그 부모는 모두 모듈 검색 경로에 있으므로, import 로직에 의해 같은 파일들이 두 가지 방법으로 발견됩니다. – user2357112

+0

오 예. 기본 스크립트의 디렉토리. 나는 항상 그 기능을 싫어했고 나는 여전히 그것을 차단하는 데 능숙합니다! 어쨌든 패키지에 내 최상위 스크립트를 두는 것을 피하여 알리지 않는 경향이 있습니다. – tdelaney

4

이것은 Enum에서는 문제가 아니지만 파이썬 가져 오기가 적용됩니다. 다른 이름으로 동일한 모듈을 가져 오면 두 개의 다른 모듈을 얻습니다.

예 : E1 is E2을 시도해보십시오.

+0

예, 가져 오기와 관련이 있지만 Enum에서는 다른 유형의 개체를 ID별로 비교하는 경우가 거의 없으므로 문제가 분명해집니다. – user443854