LEGB 규칙은 Python에서 네임스페이스(스코핑)를 찾는 규칙입니다. 약어는 다음과 같이 해석됩니다:
len, list, 등).Python이 변수를 만났을 때, 우선 로컬에서 찾고, 다음으로 중첩된 함수에서, 그 다음으로 모듈의 글로벌 영역에서, 마지막으로 내장 객체의 네임스페이스에서 찾습니다:
def outer(): x = 'enclosing' def inner(): x = 'local' print(x) inner() outer() # 'local'
만약 inner() 내부에서 x에 대한 할당을 없애면, Python은 enclosing scope(outer)에서 x를 가져옵니다. 만약 거기서도 변수가 없다면 — 글로벌에서, 그 다음 내장에서 찾습니다.
외부 수준 변수를 수정할 때
nonlocal또는global을 선언하는 것을 잊으면 함수의 동작이 어떻게 바뀔까요?
답변:
nonlocal(또는 모듈에서 변수인 경우 global)을 선언하지 않고 중첩 함수 내에서 외부 스코프의 변수를 변경하려고 하면, Python은 새로운 로컬 변수를 생성하여 외부 변수를 변경하지 않게 됩니다.
예시:
x = 10 def foo(): x = 20 # 이것은 새로운 로컬 x이며, 글로벌은 변경되지 않음 foo() print(x) # 10
글로벌 x를 변경하고 싶다면:
def foo(): global x x = 20
외부 함수의 변수와 관련해서는 nonlocal을 사용하세요.
사례 1
교육 프로젝트에서 호출 수를 계산하기 위해 중첩된 함수를 사용했습니다. 개발자는 다음과 같이 작성했습니다:
def counter(): count = 0 def inc(): count += 1 return count return inc
그러나 UnboundLocalError가 발생했습니다. 이는 inc() 내부의 count가 새로운 것으로 간주되었기 때문입니다(로컬 count가 생성됨). 해결책: count를 nonlocal로 선언합니다.
사례 2
웹 애플리케이션에서 핸들러에서 글로벌로 설정된 캐시를 수정하고자 했습니다:
cache = {} def add_to_cache(key, value): cache[key] = value
그러나 함수 내부에서 캐시를 완전히 재작성하려고 시도한 경우 cache = {key: value}, 이는 글로벌과 연결되지 않은 새로운 로컬 캐시를 생성하게 되며, global cache가 없기 때문에 발생합니다.
사례 3
대규모 ETL 시스템에서 버그가 발견되었습니다: 프로그래머가 함수 내부에서 result 변수를 명시적으로 초기화하지 않고 외부 스코프에서 가져오기를 기대했습니다. 그러나 몇 번의 반복 후 결과가 어긋나기 시작했습니다. 왜냐하면 내부에서 result += value로 작성되었고, result = result + value가 아니었기 때문입니다(물론 nonlocal/global 없이) — result는 각 호출 시에 다시 초기화되었습니다.