노트

파이썬 스코프 (LEGB)

Python Scope (LEGB Rule)

CS#python · 연결된 개념 4개

쉽게 말하면

파이썬 스코프는 이름을 부르면 우리 집, 동네, 우리 시, 나라 전체 순서로 찾아보는 규칙이에요. 가까운 곳부터 찾으니 같은 이름이 여러 곳에 있어도 어느 것을 쓸지 분명해요.

비유가 깨지는 곳 찾기는 바깥까지 가도, 함수 안 어디서든 그 이름에 대입하면 함수 전체에서 지역 변수가 돼요. 대입 전에 읽으면 UnboundLocalError가 나서, 바깥 변수를 바꾸려면 global이나 nonlocal을 선언해요.

파이썬은 이름을 찾을 때 Local → Enclosing → Global → Built-in 순서로 스코프를 뒤진다. 앞 글자를 따 LEGB(Local, Enclosing, Global, Built-in) 규칙이라 부른다. 함수 안에서 만든 변수는 그 함수 안에서만 살고, 바깥 함수의 변수는 안쪽 함수가 읽을 수 있다.

x = "global"
 
def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print(x)        # local
    inner()
    print(x)            # enclosing
 
print(len)              # built-in
  • Local: 현재 함수 안
  • Enclosing: 감싸고 있는 바깥 함수들
  • Global: 모듈 최상위
  • Built-in: len, print 같은 내장 이름

대입하면 지역 변수가 된다

함수 안 어디서든 이름에 대입하면 그 이름은 함수 전체에서 지역 변수로 취급된다. 그래서 대입 전에 읽으면 바깥 값이 아니라 UnboundLocalError가 난다.

count = 0
def inc():
    global count        # 모듈 변수를 바꾸겠다고 선언
    count += 1
 
def make_counter():
    n = 0
    def step():
        nonlocal n      # 바깥 함수 변수를 바꾸겠다고 선언
        n += 1
        return n
    return step
 
c = make_counter(); c(); c()   # 2
  • global은 모듈 변수, nonlocal은 가장 가까운 바깥 함수의 변수를 가리킨다
  • 읽기만 할 때는 선언이 필요 없다. 리스트에 append하는 것도 대입이 아니라서 선언 없이 된다

클로저

make_counter가 끝난 뒤에도 step은 n을 기억한다. 바깥 함수의 변수를 붙잡은 안쪽 함수를 클로저(closure)라 하고, 자바스크립트의 클로저와 같은 개념이다. 함수가 일급 객체(first-class object)라 변수에 담고, 인자로 넘기고, 반환할 수 있기 때문에 가능하며, 데코레이터가 이 위에 서 있다.

주의

  • 반복문 안에서 만든 람다가 반복 변수를 붙잡으면, 호출 시점의 마지막 값을 본다(늦은 바인딩, late binding). 기본 인자로 값을 고정한다: lambda i=i: i
  • 전역 변수로 함수끼리 데이터를 주고받으면 흐름을 추적하기 어렵다. 인자와 반환값으로 넘긴다(변수·컬렉션 캡슐화)
  • 내장 이름(list, id, type)을 변수명으로 덮어쓰지 않는다

스코프 규칙과 함께 함수 인자 처리는 *args·**kwargs와 언패킹, 모듈 단위의 이름 공간(namespace)은 파이썬 모듈과 패키지를 본다.

출처: Python 튜토리얼: Scopes and Namespaces · 실행 모델: Resolution of names

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 파이썬 클래스 기초

    파이썬 클래스는 데이터 속성(attribute)과 메서드를 묶은 타입이고, 클래스를 호출해 인스턴스(instance)를 만든다. 메서드의 첫 매개변수 self가 호출한 인스턴스 자신이며, 호출할 때는 파이썬이 자동으로 채워 넘긴다.

  • 가변 기본 인자 함정

    파이썬 함수의 기본값은 함수를 정의할 때 한 번 평가되어 그 객체가 계속 재사용된다. 그래서 리스트·딕셔너리 같은 변경 가능한 객체를 기본값으로 쓰면, 호출할 때마다 같은 객체가 공유되어 값이 쌓인다.

  • 파이썬 기본 컬렉션

    파이썬의 기본 컬렉션은 리스트·튜플·딕셔너리·셋 네 가지다. 가장 중요한 구분은 변경 가능 여부(mutable·immutable)와 순서·중복을 어떻게 다루는가다.

  • 매개변수 객체 만들기

    여러 함수에 늘 함께 넘겨지는 값 묶음(데이터 뭉치, Data Clumps)을 하나의 객체로 묶어 넘기는 리팩터링.

  • 얕은 복사와 깊은 복사

    얕은 복사(shallow copy)는 바깥 컨테이너만 새로 만들고 안에 든 객체는 원본과 같은 객체를 가리킨다. 깊은 복사(deep copy)는 안쪽 객체까지 재귀적으로 새로 만든다. 중첩된 리스트·딕셔너리를 복사한 뒤 원본이 같이 바뀌는 버그의 원인이 대부분 이 차이다.

보기 옵션