프로그래밍Python 개발자

'LEGB 규칙'이란 무엇인가요? 변수 이름을 찾을 때 어떻게 작동하나요? 이 규칙을 잘못 이해하여 발생하는 비트리비얼 버그에 대한 예를 들어주세요.

Hintsage AI 어시스턴트로 면접 통과

답변.

LEGB 규칙은 Python에서 네임스페이스(스코핑)를 찾는 규칙입니다. 약어는 다음과 같이 해석됩니다:

  • Local — 지역 네임스페이스(함수 내부);
  • Enclosing — 모든 중첩된 함수의 네임스페이스;
  • Global — 모듈 네임스페이스(글로벌 변수);
  • Builtin — 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는 각 호출 시에 다시 초기화되었습니다.