Python Globals, Locals 및 Unboundlocalerror
-
03-07-2019 - |
문제
나는이 사건을 가로 질러 달렸다 UnboundLocalError
최근에 이상한 것 같습니다.
import pprint
def main():
if 'pprint' in globals(): print 'pprint is in globals()'
pprint.pprint('Spam')
from pprint import pprint
pprint('Eggs')
if __name__ == '__main__': main()
생산 :
pprint is in globals()
Traceback (most recent call last):
File "weird.py", line 9, in <module>
if __name__ == '__main__': main()
File "weird.py", line 5, in main
pprint.pprint('Spam')
UnboundLocalError: local variable 'pprint' referenced before assignment
pprint
분명히 묶여 있습니다 globals
, 그리고 묶일 것입니다 locals
다음 진술에서. 누군가가 어떻게 해결되지 않는지에 대한 설명을 제공 할 수 있습니까? pprint
바인딩에 globals
여기?
편집하다: 좋은 답변 덕분에 관련 용어로 내 질문을 명확히 할 수 있습니다.
컴파일 시간에 식별자 pprint
프레임에 로컬로 표시됩니다. 실행 모델에는 차이가 없습니다 어디 프레임 내에서 로컬 식별자가 바인딩되어 있습니까? "이 바이트 코드 명령어까지 글로벌 바인딩을 참조하십시오.이 시점에서 로컬 바인딩에 반등했습니다."또는 실행 모델이이를 설명하지 않습니까?
해결책
파이썬이 보는 것 같습니다 from pprint import pprint
선과 자국 pprint
로컬 이름으로 main()
~ 전에 모든 코드 실행. Python은 Pprint가 로컬 변수가되어야한다고 생각하기 때문에 pprint.pprint()
"할당"하기 전에 from..import
진술, 그것은 그 오류를 던진다.
그것은 내가 할 수있는만큼 의미가 있습니다.
물론 도덕은 항상 import
범위의 상단에있는 진술.
다른 팁
놀람은 어디에 있습니까? 어느 변수 글로벌이 해당 범위 내에서 재 할당하는 범위에서 컴파일러에 의해 해당 범위로 로컬로 표시됩니다.
수입이 다르게 처리되면 저것 놀라운 IMHO 일 것입니다.
그러나 그 기호를 사용한 후 모듈을 명명하지 않은 경우 또는 그 반대도 마찬가지입니다.
글쎄, 그것은 내가 조금 실험 할 정도로 흥미로 웠고 나는 http://docs.python.org/reference/executionmodel.html
그런 다음 여기 저기 코드를 땜질했습니다. 이것이 제가 찾을 수있는 것입니다.
암호:
import pprint
def two():
from pprint import pprint
print globals()['pprint']
pprint('Eggs')
print globals()['pprint']
def main():
if 'pprint' in globals():
print 'pprint is in globals()'
global pprint
print globals()['pprint']
pprint.pprint('Spam')
from pprint import pprint
print globals()['pprint']
pprint('Eggs')
def three():
print globals()['pprint']
pprint.pprint('Spam')
if __name__ == '__main__':
two()
print('\n')
three()
print('\n')
main()
산출:
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Eggs'
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Spam'
pprint is in globals()
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Spam'
<function pprint at 0xb7d596f4>
'Eggs'
방법에서 two()
from pprint import pprint
그러나 이름을 무시하지 않습니다 pprint
안에 globals
, 이후 global
키워드입니다 ~ 아니다 범위에서 사용됩니다 two()
.
방법에서 three()
선언이 없기 때문에 pprint
로컬 범위의 이름은 기본적으로 글로벌 이름으로 표시됩니다. pprint
이것은 모듈입니다
반면 main()
, 처음에는 키워드입니다 global
사용 그래서 모든 참조 pprint
방법의 범위에서 main()
will refer to the global
이름 pprint
. 우리가 볼 수 있듯이 처음에는 모듈이며 global
namespace
우리가하는 방법으로 from pprint import pprint
이것은 그 질문에 대답하지는 않지만 그럼에도 불구하고 내가 생각하는 흥미로운 사실.
=====================
편집하다 또 다른 흥미로운 것.
모듈이있는 경우 :
mod1
from datetime import datetime
def foo():
print "bar"
그리고 또 다른 방법은 다음과 같습니다.
mod2
import datetime
from mod1 import *
if __name__ == '__main__':
print datetime.datetime.now()
모듈을 가져온 이후 첫눈에 맞는 것 같습니다. datetime
안에 mod2
.
이제 mod2를 스크립트로 실행하려고하면 오류가 발생합니다.
Traceback (most recent call last):
File "mod2.py", line 5, in <module>
print datetime.datetime.now()
AttributeError: type object 'datetime.datetime' has no attribute 'datetime'
두 번째 가져 오기 때문입니다 from mod2 import *
이름을 재정의했습니다 datetime
네임 스페이스에서는 첫 번째입니다 import datetime
더 이상 유효하지 않습니다.
도덕 : 따라서 수입 순서, 수입의 특성 (X 가져 오기 *) 및 수입 모듈 내에서 수입에 대한 인식 - 문제.
이 질문은 몇 주 전에 답변되었지만 답을 조금 명확히 할 수 있다고 생각합니다. 먼저 몇 가지 사실.
1 : 파이썬에서
import foo
거의 정확히 동일합니다
foo = __import__("foo", globals(), locals(), [], -1)
2 : 함수에서 코드를 실행할 때 Python이 함수에서 아직 정의되지 않은 변수가 발생하면 전역 범위가 보입니다.
3 : Python은 "현지인"이라는 기능에 사용하는 최적화를 가지고 있습니다. Python이 함수를 토큰 화하면 할당 한 모든 변수를 추적합니다. 이 변수는 각 변수에 로컬 단조로 증가하는 정수에서 숫자를 할당합니다. Python이 함수를 실행하면 로컬 변수만큼 많은 슬롯이있는 배열을 생성하고 각 슬롯을 "아직 할당되지 않은"것을 의미하는 특수 값을 할당하며 해당 변수의 값이 저장됩니다. 아직 할당되지 않은 로컬을 참조하면 Python은 그 특별한 가치를보고 UnboundLocalValue 예외를 던졌습니다.
이제 무대가 설정되었습니다. "PPRINT 가져 오기 PPRINT"는 실제로 할당의 형태입니다. 따라서 Python은 글로벌 변수를 막는 "pprint"라는 로컬 변수를 만듭니다. 그런 다음 함수에서 "pprint.pprint"를 참조하면 특수 값을 누르고 Python은 예외를 던졌습니다. 이 기능에 해당 가져 오기 명령문이없는 경우 Python은 일반적인 Look-in-Locals-ther-then-then-in-globals 해상도를 사용하고 Globals에서 Pprint 모듈을 찾을 수 있습니다.
이를 명확하게하기 위해 "글로벌"키워드를 사용할 수 있습니다. 물론 지금까지 당신은 이미 당신의 문제를 지나서 일했으며, 당신이 실제로 "글로벌"이 필요했는지 또는 다른 접근법이 요구되었는지 모르겠습니다.