파이썬/기초 프로그래밍

파이썬 클로저와 nonlocal — 언제 필요할까?

Data Jun 2025. 9. 8. 09:32

nonlocal이 필요한 경우와 필요 없는 경우

파이썬에서 내부 함수가 외부 변수를 다룰 때, 두 가지 경우가 있습니다:

 

1. 변경(뮤테이션, mutation)만 하는 경우 → nonlocal 불필요

def closure_ex1():
    series = []   # 리스트 (가변 객체)

    def averager(v):
        series.append(v)  # 리스트 내부 수정
        return sum(series) / len(series)

    return averager

avg = closure_ex1()
print(avg(10))  # 10.0
print(avg(20))  # 15.0
  • series.append(v)는 리스트 내부를 수정하는 동작(뮤테이션)
  • series 자체를 새로 대입하지 않으므로, 파이썬은 그냥 외부 변수를 참조
  • nonlocal 필요 없음

 

2. 재할당(reassignment) 하는 경우 → nonlocal 필요

def closure_ex2():
    cnt = 0       # 정수 (불변 객체)
    total = 0

    def averager(v):
        nonlocal cnt, total  # 외부 변수 사용을 명시
        cnt += 1             # cnt = cnt + 1 (재할당 발생)
        total += v           # total = total + v (재할당 발생)
        return total / cnt

    return averager

avg = closure_ex2()
print(avg(10))  # 10.0
print(avg(30))  # 20.0
  • cnt += 1은 사실상 cnt = cnt + 1 → 변수에 새 값을 대입하는 것
  • 이때 nonlocal을 쓰지 않으면 파이썬은 cnt를 내부 함수의 지역 변수로 인식해버림
  • 아직 초기화되지 않은 지역 변수를 읽으려 하니 UnboundLocalError 발생
  • nonlocal로 “바깥 변수 쓰겠다” 명시해야 함

 

 

정리하면

    • 클로저는 외부 변수를 기억한다.
    • 하지만 내부 함수에서 그 변수를 **재할당하려면 반드시 nonlocal**을 사용해야 한다.
    • 반대로 가변 객체의 내용만 수정한다면 nonlocal 없이도 동작한다.