Python Unbound LocalError 와 NameError 오류 근원 사례 분석
본 고 는 폐쇄 와 관련 된 개념 을 이해 하기 위해 자 리 를 깔 고 후속 적 으로 폐쇄 와 관련 된 박문 을 상세 하 게 정리 할 것 이 니 주목 해 주시 기 바 랍 니 다.
1.사례 분석
패 킷 관련 개념 을 정리 하 는 과정 에서 언 바 운 드 로 컬 에 러 와 네 임 에 러 라 는 두 가지 오류 가 자주 발견 되 는데,처음 만 났 을 때 곤 혹 스 러 웠 을 수도 있 고 이런 오류 에 손 을 댈 수가 없 었 다.
1.1 사례 1:
def outer_func():
loc_var = "local variable"
def inner_func():
loc_var += " in inner func"
return loc_var
return inner_func
clo_func = outer_func()
clo_func()
오류 알림:Traceback (most recent call last):
File "G:\Project Files\Python Test\Main.py", line 238, in
clo_func()
File "G:\Project Files\Python Test\Main.py", line 233, in inner_func
loc_var += " in inner func"
UnboundLocalError: local variable 'loc_var' referenced before assignment
1.2 사례 2:
def get_select_desc(name, flag, is_format = True):
if flag:
sel_res = 'Do select name = %s' % name
return sel_res if is_format else name
get_select_desc('Error', False, True)
오류 알림:Traceback (most recent call last):
File "G:\Project Files\Python Test\Main.py", line 247, in
get_select_desc('Error', False, True)
File "G:\Project Files\Python Test\Main.py", line 245, in get_select_desc
return sel_res if is_format else name
UnboundLocalError: local variable 'sel_res' referenced before assignment
1.3 사례 3:
def outer_func(out_flag):
if out_flag:
loc_var1 = 'local variable with flag'
else:
loc_var2 = 'local variable without flag'
def inner_func(in_flag):
return loc_var1 if in_flag else loc_var2
return inner_func
clo_func = outer_func(True)
print clo_func(False)
오류 알림:Traceback (most recent call last):
File "G:\Project Files\Python Test\Main.py", line 260, in
print clo_func(False)
File "G:\Project Files\Python Test\Main.py", line 256, in inner_func
return loc_var1 if in_flag else loc_var2
NameError: free variable 'loc_var2' referenced before assignment in enclosing scope
위의 세 가지 예 는 약간 가식 적 으로 보일 수 있 지만 실제 적 으로 잘못된 코드 와 비슷 한 것 은 위의 예 에서 그림 자 를 찾 을 수 있다.이것 은 단지 관련 개념 을 설명 하기 위해 서 예 자체 의 합 리 성에 대해 지나치게 관심 을 가 질 필요 가 없다.
2.오류 원인
python 에는 변수,함수 또는 클래스 의 성명 개념 이 없 기 때 문 입 니 다.C 나 C++의 습관 에 따라 python 을 작성 하면 잘못된 근원 이 어디 에 있 는 지 찾기 어 려 울 수도 있 습 니 다.
우선 이런 잘못된 공식 해석 을 살 펴 보 자.
When a name is not found at all, a NameError exception is raised. If the name refers to a local variable that has not been bound, a UnboundLocalError exception is raised. UnboundLocalError is a subclass of NameError.
대충
어떤 변 수 를 인 용 했 지만 변수 이름 을 찾 지 못 하면 이 유형의 오 류 는 NameError 입 니 다.이 이름 이 아직 연결 되 지 않 은 부분 변수 이름 이 라면 이 유형의 오 류 는 NameError 의 Unbound LocalError 오류 입 니 다.
아래 의 이러한 NameError 유형의 오 류 는 아마도 좀 더 이해 할 수 있 을 것 이다.
my_function()
def my_function():
pass
python 해석 기 가 def my 까지 실행 된다 면function()시 my 에 귀속function,myfunction 이때 도 메모리 에서 함수 가 실 행 된 입 구 를 표시 합 니 다.그래서 그 전에 my 를 사용 합 니 다.function 에 모두 NameError 오류 가 있 을 수 있 습 니 다.그러면 위의 예 에서 변 수 를 사용 하기 전에 할당 작업(바 인 딩 작업 으로 볼 수 있 고 나중에 말 할 수 있 습 니 다)이 있 습 니 다.왜 인용 할 때 오류 가 발생 합 니까?정의 도 가시 성 을 판단 할 수 있다
할당 작업 이 실행 되 지 않 았 기 때 문 이 라면 왜 이 변수 이름 은 부분 네 임 스페이스 에서 볼 수 있 습 니까?(보이 지 않 으 면 이러한 오류 가 발생 합 니 다:NameError:global name'xxx'is not defined,Unbound LocalError 정의 에 따라 가시 성 을 판단 할 수 있 습 니 다)
문 제 는 도대체 어디 에 있 습 니까?어떻게 위의 세 가지 예 중의 잘못 을 정확하게 이해 합 니까?
3.가시 성과 귀속
간단히 말 해서 네 임 스페이스 와 변수 찾기 규칙 LGB 와 관련 된 개념 은 소개 하지 않 습 니 다.
C 나 C++에 서 는 변수 나 함 수 를 설명 하고 정의 하면 직접 사용 할 수 있 습 니 다.그러나 Python 에서 name 을 인용 하려 면 이 name 을 볼 수 있 고 연결 되 어 있어 야 합 니 다.
먼저 몇 가지 개념 을 알 아 보 자.
1.codeblock:하나의 단원(Unit)으로 실 행 된 python 프로그램 텍스트 입 니 다.예 를 들 어 하나의 모듈,함수 체 와 클래스 의 정의 등 이다.
2.scope:code block 에서 name 의 가시 성 을 정의 합 니 다.
3.block's environment:하나의 code block 에 대해 모든 scope 에서 볼 수 있 는 name 의 집합 은 block 의 환경 을 구성 합 니 다.
4.bid name:아래 동작 은 모두 바 인 딩 작업•함수 의 형 삼 으로 볼 수 있 습 니 다.
•import 성명
클래스 와 함수 의 정의
할당 작업
for 순환 첫 번 째 표지
•이상 캡 처 와 관련 된 할당 변수
5.local variable:name 이 하나의 block 에 연결 되면 이 변 수 는 이 block 의 local variable 입 니 다.
6.global variable:name 이 하나의 module 에 연결 되면 이 변 수 는 global variable 라 고 합 니 다.
7.free variable:하나의 name 이 하나의 block 에서 인용 되 었 으 나 이 코드 블록 에서 정의 되 지 않 았 다 면 이 변 수 를 free variable 라 고 부 릅 니 다.
Free variable 은 비교적 중요 한 개념 으로 패키지 에서 인용 한 부모 함수 의 국부 변 수 는 free variable 이 며,이 free variable 는 cell 대상 에 저 장 됩 니 다.이 건 폐쇄 관련 글 에서 소개 할 게 요.
scope 는 함수 에서 확장 성 이 있 지만 클래스 정의 에 서 는 확장 성 이 없습니다.
분석 정리:
위의 개념 소 개 를 통 해 알 수 있 듯 이 하나의 변 수 는 codeblock 에 바 인 딩 작업 이 있 으 면 codeblock 의 scope 에 이 변 수 를 포함 합 니 다.
즉,바 인 딩 작업 이 결정 되 었 습 니 다.바 인 딩 된 name 은 현재 scope(함수 라면 정 의 된 scope 포함)에서 볼 수 있 습 니 다.name 에서 진정한 바 인 딩 작업 을 하기 전에 도 볼 수 있 습 니 다.
연결 name 작업 전에 이 name 을 인용 하면 문제 가 발생 합 니 다.이 name 이 보 여도.
If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.
위 에서 공식 적 으로 묘사 한 첫 마디 와 마지막 한 마디 에 주의 하 세 요.
전체적으로 말 하면 하나의 code block 에서 모든 바 인 딩 작업 에서 바 인 딩 된 name 은 local variable 로 볼 수 있 습 니 다.그러나 바 인 딩 작업 이 실 행 될 때 까지 이 name 을 진정 으로 참조 할 수 있 습 니 다.
이런 개념 이 있 으 면 아래 에 위의 세 가지 사례 를 하나씩 분석 해 보 자.
4.오류 해석
4.1 사례 분석
outer 에서func 에서 변 수 를 정 의 했 습 니 다 locvar,할당 은 바 인 딩 작업 이기 때문에 locvar 는 가시 성 이 있 고 구체 적 인 문자열 대상 에 연결 되 어 있 습 니 다.
하지만 그 중에서 정 의 된 함수 innerfunc 에 서 는 인용 할 수 없습니다.함수 에 있 는 scope 는 그 안에 정 의 된 모든 scope 로 확장 할 수 있 지 않 습 니까?
다음은 공식 적 인 두 단락 의 설명 을 살 펴 보 겠 습 니 다.
When a name is used in a code block, it is resolved using the nearest enclosing scope.
이 말 은 name 이 인 용 될 때 가장 가 까 운 scope 에서 인 용 된 name 의 정 의 를 찾 는 것 을 알려 줍 니 다.분명히 locvar+="in inner func"이 문장의 locvar 는 내부 함수 innerfunc 에서 name loc 찾기var。
이 문 구 는 실제로 loc 와 같다.var = loc_var+"in inner func",등호 오른쪽 locvar 변 수 는 먼저 사용 되 지만,여 기 는 outer 를 사용 하지 않 습 니 다.func 에서 정의 하 는 locvar,함수 innerfunc 의 scope 중 locvar 의 할당 작업 이 므 로 이 변 수 는 inner 에 있 습 니 다.func 의 scope 에서 inner 로func 의 local variable 는 볼 수 있 습 니 다.
하지만 이 문구 가 실 행 될 때 까지 기 다 려 야 loc 를 진정 으로 연결 할 수 있 습 니 다.var。바로 이 문장에서 우 리 는 inner 를 사용 했다func block 에 연결 되 기 전의 local variable 입 니 다.위의 오류 형식의 정의 에 따 르 면 이것 은 Unbound Local Error 입 니 다.
4.2 사례 2 분석
이 예 에서 문제 가 있 는 것 처럼 보이 지만 어떻게 설명해 야 할 지 모르겠다.
인용 은 바 인 딩 작업 후에 발생 합 니 다.이 변 수 는 정상적으로 인 용 될 수 있 을 것 입 니 다.문 제 는 할당 문(바 인 딩 작업)이 반드시 실행 되 는 것 은 아니 라 는 점 이다.바 인 딩 작업 이 없 으 면 변수 에 대한 인용 에 문제 가 있 을 것 입 니 다.이 앞 에 설명 되 어 있 습 니 다.
그러나 또 하나의 의문 은 할당 문 이 실행 되 지 않 았 다 면 변 수 는 현재 block 에서 왜 볼 수 있 습 니까?
이 문제 에 대해 서 는 위 에서 설명 할 수 있 습 니 다.The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.
바 인 딩 작업(실제 실행 되 었 든 안 되 었 든)이 있 으 면 바 인 딩 된 name 은 local variable,즉 현재 block 에서 볼 수 있 습 니 다.scanning text 는 코드 가 실행 되 기 전에 발생 합 니 다.
4.2 사례 3 분석
이 예 는 주로 free variable 에 대한 인용 문 제 를 설명 한다.동시에 이 예 는 free variable 의 사용 도 보 여 주 었 다.
클 로즈 드 inner 만 들 기func 시,locvar 1 과 locvar 2 부모 함수 outerfunc 의 두 local variable 내부 innerfunc 의 scope 에서 볼 수 있 습 니 다.닫 힌 가방 으로 돌아 간 후 닫 힌 가방 에서 outer 참조func 의 local variable 는 free variable 이 라 고 합 니 다.
패키지 에 있 는 free variable 가 인용 되 는 지 여 부 는 구체 적 인 대상 에 연결 되 어 있 는 지 여부 에 달 려 있 습 니 다.
5.사례 설명
다음은 예 를 하나 더 보 겠 습 니 다.
import sys
def add_path(new_path):
path_list = sys.path
if new_path not in path_list:
import sys
sys.path.append(new_path)
add_path('./')
평소 무심코 위 에 있 는 이 오 류 를 범 할 수 있 는 것 도 전형 적 인 언 바 운 드 로 컬 오류 다.위의 분석 과정 을 자세히 읽 고 이해 하면 이 오 류 를 이해 할 수 있 는 원인 이 될 것 이 라 고 믿는다.아직 지우 지 않 으 면 다시 한 번 읽 어 주세요.-)총결산
위 에서 말 한 것 은 편집장 님 께 서 소개 해 주신 Python Unbound LocalError 와 NameError 오류 의 근원 사례 분석 입 니 다.여러분 께 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.편집장 님 께 서 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.