Python 함수의 범위 규칙


Python은 그 자체로는 동적 언어이지만 정적으로 범위가 지정된 언어입니다. 즉, Python에서 변수의 범위는 소스 코드에서의 위치에 따라 결정되는데, 이는 C와 다소 유사하지만 Python과 C의 범위 차이는 여전히 매우 분명합니다.


다음으로 Python의 범위 규칙에 대해 이야기하고, 범위 측면에서 Python과 C의 차이점도 설명하겠습니다.

Python 2.0 및 이전 버전에서 Python은 Python 2.2에서 로컬 범위, 전역 범위, 내장 범위라는 세 가지 유형의 범위만 지원합니다. Python은 공식적으로 새로운 범위 --- 중첩을 도입했습니다. 범위; Python 2.1에서는 중첩 범위를 옵션으로 설정할 수 있습니다. 중첩 범위의 도입은 기본적으로 Python에 클로저에 대한 지원을 제공합니다. 인터넷에는 많은 설명이 있으므로 여기서는 자세히 설명하지 않겠습니다. . 이에 따라 변수 검색 순서가 이전 LGB에서 LEGB(L: Local, E: Enclosing, G: Global, B: 내장)로 변경됩니다.


Python에서는 어떤 코드 블록도 C와 매우 다른 새로운 범위를 도입할 수 없습니다.

#🎜 🎜#

#include<stdio.h>int main() {    if(2 > 0) {        int i = 0;
    }
    printf("i = %d", i);    return 0;
}

이 코드에서 if 절은 로컬 범위를 소개하며 변수 i는 이 로컬 범위에 존재합니다. , 그러나 외부 세계에는 표시되지 않습니다. 따라서 printf 함수에서 변수 i에 대한 후속 참조는 컴파일 오류를 발생시킵니다.

그러나 Python에서는 그렇지 않습니다.

if True:
    i = 0print i
이 코드에서 if 절은 로컬 범위를 도입하지 않습니다. 변수 i는 여전히 전역 범위에 있으므로 변수 i는 후속 print 문에서 볼 수 있습니다.

사실 Python에서는 모듈, 클래스, 함수만 새 범위를 도입하고 다른 코드 블록에서는 새 범위를 도입하지 않습니다.

Python에서는 변수를 사용하기 전에 미리 선언할 필요가 없지만 실제로 사용하기 전에 개체에 바인딩되어 있어야 하며 이름 바인딩을 통해 새 변수가 생성됩니다. 현재 범위 변수이며 현재 범위에서 이름 바인딩이 발생하는 위치에 관계없이 외부 범위에서 동일한 이름으로 변수를 마스크합니다.

def f():    print i
f()


실행 결과에는 다음이 표시됩니다. NameError: 전역 이름 'i'가 정의되지 않았습니다. Python은 먼저 함수 f의 로컬 범위에서 변수 i를 검색하고 검색에 실패합니다. 그런 다음 전역 범위와 내장 범위에서 변수 i를 검색하지만 여전히 실패하고 마지막으로 NameError 예외가 발생합니다.

i = 0def f():
    i = 8    print i
f()print i


실행 결과는 8과 0입니다. i = 8은 함수 f의 로컬 범위에 새 변수 i를 도입하고 전역 변수 i를 차단합니다. 따라서 f 내부의 print 문은 지역 변수 i를 보고 f 외부의 print 문은 지역 변수 i. 명령문이 보는 것은 전역 변수 i입니다.

i = 0def f():    print i
    i = 0
f()


실행 결과는 다음과 같습니다. UnboundLocalError: 할당 전에 지역 변수 'i'가 참조되었습니다. 이 예에서 함수 f의 변수 i는 지역 변수이지만 print 문에서 이를 사용할 때 어떤 개체에도 바인딩되지 않았으므로 예외가 발생합니다.

print i
i = 0


대화식으로 실행하든 스크립트 파일로 실행하든 결과는 다음과 같습니다. NameError: name 'i'가 정의되지 않았습니다. 여기의 출력은 최상위 범위(모듈 범위)에 있기 때문에 이전 예제와 다릅니다. 모듈 코드의 경우 코드가 실행되기 전에 어떠한 전처리도 거치지 않지만, 함수 본문의 경우 코드가 실행되기 전에 이미 전처리를 거쳤기 때문에 범위 내 어디에서 이름 바인딩이 발생하더라도 느낄 수 있습니다. Python은 정적으로 범위가 지정된 언어이지만 이름 조회는 동적으로 발생하므로 이름 문제는 런타임까지 발견되지 않습니다.


Python에서 이름 바인딩은 해당 변수가 속한 범위에 새 변수를 도입하고 개체에 바인딩합니다. 이름 바인딩은 다음 상황에서 발생합니다.


  1. 매개변수 선언: #🎜🎜 #매개변수 선언이 소개됩니다. 함수의 로컬 범위에 있는 새 변수
  2. 할당 작업: 변수에 대한 수행 초기 할당이 소개됩니다. 현재 범위의 새 변수와 후속 할당 작업은 변수를 다시 바인딩합니다. 함수 정의: 클래스 및 함수 정의는 클래스 이름과 함수 이름을 현재 범위에 변수로 도입하고 클래스 본문과 함수 본문은 다른 범위를 형성합니다.
  3. #🎜🎜 #
  4. import 문: import 문은 일반적으로 전역에서 현재 범위에 새 변수를 도입합니다.
    #🎜🎜 #
  5. for 문: for 문은 현재 범위에 새로운 변수(루프 변수)를 도입합니다. 🎜##🎜 🎜#
    제외 문:
  6. 제외 문은 현재 범위에 새 변수(예외 개체)를 도입합니다.

  7. Python에서 클래스 정의에 의해 도입된 범위는 멤버 함수에 보이지 않습니다. 는 C++ 또는 Java와 매우 다르기 때문에 Python에서 멤버 함수가 클래스 본문에 정의된 변수를 참조하려면 self 또는 클래스 이름을 통해 이를 참조해야 합니다.
    중첩된 범위를 추가하면 일부 코드가 컴파일되지 않거나 다른 실행 결과를 얻게 됩니다. 여기서 Python 인터프리터는 이러한 경고가 무엇인지 식별하는 데 도움이 됩니다. 문제가 발생할 수 있는 경우.


locals 함수는 모든 지역 변수를 반환하지만 중첩된 범위의 변수는 반환하지 않습니다. 실제로 .