무엇이 잘못됐나요
파이썬에서 global을 사용하면 이 함수에 전역 변수를 사용할 수 있습니다. 동시에 함수 내의 변수에 액세스하는 것은 먼저 로컬이고 그 다음에는 전역입니다.
중첩된 함수에서 전역을 사용하면 비합리적인 동작이 발생합니다.
상위 코드:
In [96]: def x(): b = 12 def y(): global a,b a = 1 b = 2 y() print "b =",b ....: In [97]: a = 111 In [98]: del b In [99]: x() b = 12 In [100]: a Out[100]: 1 In [101]: b Out[101]: 2
함수 x()에서는 global을 사용하지 않고, b는 이때 local을 사용합니다. 따라서 print는 로컬 b를 인쇄합니다
왜 12가 인쇄되나요? 그리고 In[101]의 b가 2라는 것을 어떻게 설명할 수 있나요?
y(), 사용된 전역은 x()의 b = 12를 가져오지 않습니다.
함수 y()에서 global a,b 문은 a와 b를 전역으로 확장하므로 최상위 수준에서는 b(In[98])가 없더라도 b(In[101])는 생성되었습니다.
즉, 전역 a,b는 a와 b를 가장 바깥쪽 변수로 간주합니다.
다시 시도하세요:
In [102]: def x(): b = 12 def y(): global a,b a = 1 y() print "b =",b .....: In [103]: a = 111 In [104]: del b In [105]: x() b = 12 In [106]: a Out[106]: 1 In [107]: b --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-107-3b5d5c371295> in <module>() ----> 1 b NameError: name 'b' is not defined
오류가 보고되었습니다! y() 전역 b 이후에 할당이 없으면 최상위 수준에는 b가 없습니다. 이는 전역이 이름만 소개하고 할당과 같은 작업을 수행하지 않음을 보여줍니다.
global은 변수의 존재 여부에 상관하지 않고 이름만 가져오고 이름에 대한 작업은 '최상위 네임스페이스'에 반영됩니다.
또 오세요:
In [109]: a = 111 In [110]: del b --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-110-745f2abe7045> in <module>() ----> 1 del b NameError: name 'b' is not defined In [111]: def x(): b = 12 def y(): global a,b a = 1 print b y() print "b =",b .....: In [112]: x() --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-112-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-111-c05fc67a1e82> in x() 5 a = 1 6 print b ----> 7 y() 8 print "b =",b 9 <ipython-input-111-c05fc67a1e82> in y() 4 global a,b 5 a = 1 ----> 6 print b 7 y() 8 print "b =",b NameError: global name 'b' is not defined
이는 내부 레이어 y()의 전역이 x()의 항목을 가져오지 않음을 확인합니다.
그러면 내부 함수는 외부 함수의 올바른 변수를 어떻게 사용합니까?
내부 함수 매개변수 전달 문제 해결
1.
우선 값만 얻으면 아무런 처리도 할 필요가 없습니다.
In [119]: def x(): .....: a = 12 .....: def y(): .....: print a .....: y() .....: In [120]: x() 12 In [121]:
y()에서는 a에 값이 할당되면 즉시 내부 변수가 됩니다.
In [121]: def x(): .....: a = 12 .....: def y(): .....: print "before a =",a .....: a = 1 .....: print "then a =",a .....: y() .....: In [122]: x() before a =--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-122-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-121-d8fbc0dba399> in x() 5 a = 1 6 print "then a =",a ----> 7 y() 8 <ipython-input-121-d8fbc0dba399> in y() 2 a = 12 3 def y(): ----> 4 print "before a =",a 5 a = 1 6 print "then a =",a UnboundLocalError: local variable 'a' referenced before assignment
a에 y() 함수 어딘가에 값이 할당되면 Python은 할당 전에 a가 존재하지 않는다고 생각합니다.
동시에 python2의 프린트가 하나씩 출력되는 것을 발견했습니다. 그런 점에서 다시 python3에서 시도해 보았는데, 같이 출력되는 것을 발견했습니다. 하지만 이 글의 초점은 이것이 아니므로 접겠습니다.
In [7]: def x(): a = 1 def y(): print("before a=",a) a = 10 print("then a=",a) y() ...: In [8]: x() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-8-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-7-6e01e7317b24> in x() a = 10 print("then a=",a) ----> 7 y() <ipython-input-7-6e01e7317b24> in y() a = 1 def y(): ----> 4 print("before a=",a) a = 10 print("then a=",a) UnboundLocalError: local variable 'a' referenced before assignment
동시에 Python 코드를 실행하기 전에 단순히 한 줄씩 실행하는 것이 아니라 먼저 코드를 스캔한다는 사실을 발견했습니다.
NameError 대신 UnboundLocalError가 반환되는 것도 발견되었습니다. 공식적인 개념인 '언바운드'에 주목하세요. 설명하기 위해 'unbound'를 사용하는 것은 다음과 같습니다. global은 최상위 변수 이름을 지역 변수 이름에 바인딩하고 동시에 변경합니다. 이는 Python이 a = 1을 감지하면 a가 '참조'임을 인식합니다. 로컬이므로 a가 '객체를 가리킬' 때(파이썬 변수는 모두 참조이기 때문에) a를 호출하는 것은 이전에는 잘못된 동작이었지만 이 동작은 NameError와 다르며 바인딩되지 않은 로컬로 정의됩니다.
2.
list, dict 등 변수 변수를 사용하세요
In [127]: def x(): .....: l = ["in msg"] .....: def y(): .....: msg = l[0] .....: print "msg =",msg .....: l[:] = ["out msg"] .....: y() .....: print l[0] .....: In [128]: x() msg = in msg out msg
오류도 없고 완벽해요!
l[:] = ["out msg"] 문에 주의하고 슬라이스 할당을 사용하세요. 그렇지 않으면
In [129]: def x(): l = ["in msg"] def y(): msg = l[0] print "msg =",msg l = ["out msg"] y() print l[0] .....: In [130]: x() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-130-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-129-d44e750e285f> in x() 5 print "msg =",msg 6 l = ["out msg"] ----> 7 y() 8 print l[0] 9 <ipython-input-129-d44e750e285f> in y() 2 l = ["in msg"] 3 def y(): ----> 4 msg = l[0] 5 print "msg =",msg 6 l = ["out msg"] UnboundLocalError: local variable 'l' referenced before assignment
6번째 코드 줄이 l에 새 목록을 할당하기 때문에 UnboundLocalError가 다시 발생합니다.
3.
매개변수 전달을 사용하세요.
In [136]: def x(): .....: a, b = 1, 2 .....: def y(a = a, b = b): .....: a, b = 3, 4 .....: return a, b .....: a, b = y() .....: print a, b .....: In [137]: x() 3 4
기본 매개변수에 목록 등의 변수 객체를 넣지 않도록 주의하세요.
위 내용은 편집자가 소개한 PYTHON에서 GLOBAL을 사용하면서 발생하는 일련의 문제입니다. 궁금한 점이 있으시면 메시지를 남겨주시면 편집자가 답변해 드리겠습니다. 시간에. 또한 Script House 웹사이트를 지원해 주신 모든 분들께 감사의 말씀을 전하고 싶습니다!