파이썬/기초 프로그래밍

파이썬 클로저(Closure)와 nonlocal 키워드

Data Jun 2025. 9. 8. 09:28

1. 클로저(Closure) 

클로저는 함수가 자신을 둘러싼 스코프(외부 함수)의 변수를 캡처해서 기억하는 함수입니다.
외부 함수가 끝나도, 내부 함수는 그 변수를 계속 사용할 수 있어요.

 

2. 예제: nonlocal을 이용한 평균 계산기

# Nonlocal -> Free variable
def closure_ex3():
    # 자유 변수(Free variable)
    cnt = 0
    total = 0
    
    def averager(v):
        nonlocal cnt, total
        cnt += 1
        total += v
        return total / cnt
    
    return averager

avg_closure3 = closure_ex3()

print(avg_closure3(15))  # 15.0
print(avg_closure3(35))  # 25.0
print(avg_closure3(40))  # 30.0

 

1️⃣ nonlocal이 왜 필요할까?

  • cnt와 total은 외부 함수(closure_ex3)에 정의된 자유 변수입니다.
  • 내부 함수 averager에서 이 변수들을 재할당(= 새로운 값으로 바꾸기) 하려면 문제가 생겨요.
    • 그냥 쓰면 파이썬은 cnt, total을 지역 변수로 간주해버려서 UnboundLocalError 발생.
  • nonlocal cnt, total을 선언하면,
     “이 변수는 지역 변수가 아니라 바깥 함수(closure_ex3)의 변수를 쓰겠다”라고 명시하는 것.

즉, nonlocal 덕분에 외부 함수의 변수를 안전하게 수정할 수 있습니다.

 

2️⃣ 실행 흐름

  1. closure_ex3() 실행 → cnt=0, total=0 생성
  2. averager 반환 (클로저 함수)
  3. avg_closure3(15) 호출
    • cnt=1, total=15, 결과 15.0
  4. avg_closure3(35) 호출
    • cnt=2, total=50, 결과 25.0
  5. avg_closure3(40) 호출
    • cnt=3, total=90, 결과 30.0

외부 함수는 이미 끝났지만, 내부 함수는 cnt와 total을 계속 기억하면서 업데이트합니다.

 

3. nonlocal vs global

  • global: 모듈 전체에서 접근 가능한 전역 변수 수정
  • nonlocal: 바로 바깥 함수(로컬 스코프)의 변수를 수정

클로저 내부에서 상태를 관리할 땐 nonlocal을 써야 합니다.

 

 

 

정리하면

  • 클로저는 외부 함수의 변수를 기억하는 함수
  • nonlocal은 내부 함수에서 외부 함수 변수 재할당 시 꼭 필요
  • 덕분에 클로저는 상태를 가진 함수처럼 동작할 수 있음