파이썬/기초 프로그래밍

파이썬 클로저(Closure) 간단 이해 + 내부 구조 들여다보기

Data Jun 2025. 9. 8. 09:19

1. 클로저가 뭐지?

클로저는 “함수가 만들어질 때의 외부 변수(자유 변수) 를 기억했다가, 나중에 함수를 호출할 때도 그 값을 계속 사용할 수 있는” 함수예요. 클래스를 쓰지 않아도 상태를 은근슬쩍 유지할 수 있다는 게 장점입니다

 

예제: 평균 누적 함수 만들기

# Closure 사용
def closure_ex1():
    # 자유변수 / 클로저 영역
    series = []

    def averager(v):
        series.append(v)
        print('inner >> {} / {}'.format(series, len(series)))
        return sum(series) / len(series)

    return averager

avg_closure1 = closure_ex1()

# 누적
print(avg_closure1(10))  # 10.0
print(avg_closure1(20))  # 15.0
print(avg_closure1(30))  # 20.0

어떻게 동작하나?

  • closure_ex1()가 실행될 때 series = []가 만들어집니다.
  • 내부 함수 averager는 바깥 스코프의 series를 캡처합니다.
  • closure_ex1()은 averager를 반환하고 끝나지만, averager는 series를 기억하고 있어요.
  • 그래서 avg_closure1(…)를 여러 번 호출해도 series에 값이 계속 누적됩니다.

 

2. 클로저 내부 들여다보기(inspection)

파이썬은 함수 객체가 내부 정보를 꽤 많이 노출합니다. 아래 코드는 그중 클로저 관련 속성 위주로 확인한 예예요.

# function inspection
print(dir(avg_closure1))              # 함수 객체가 가진 속성들
print()
print(dir(avg_closure1.__code__))     # 코드 객체가 가진 속성들
print()
print(avg_closure1.__code__.co_freevars)  # ('series',) - 캡처된 자유 변수 이름
print()
print(dir(avg_closure1.__closure__[0]))   # 클로저 셀(cell) 객체 속성
print()
print(avg_closure1.__closure__[0].cell_contents)  # 실제로 캡처된 값: series 리스트 내용
print()

설명

  • __code__.co_freevars
    자유 변수 이름들의 튜플. 위 예제에선 ('series',)가 나옵니다.
  • __closure__
    셀(cell) 객체들의 튜플. 각 셀에 자유 변수의 실제 값이 담겨 있어요.
    • avg_closure1.__closure__[0].cell_contents
      → series의 현재 리스트 내용이 그대로 보입니다(예: [10, 20, 30]).

이 함수가 어떤 외부 변수를 캡처했는지(co_freevars), 그 실제 값이 무엇인지(closure … cell_contents) 를 직접 확인할 수 있다!

 

3. 언제 클로저를 쓰면 좋을까?

  • 상태를 가진 작은 함수가 필요할 때(카운터, 평균, 최근값 유지 등)
  • 클래스 만들기엔 과하지만 간단한 상태 유지가 필요할 때
  • 콜백/고차함수에서 컨텍스트 일부를 묶어두고 싶을 때

 

4. 클래스의 __call__과 비교 

  • 클로저: 함수가 외부 변수를 캡처해서 상태를 “기억”
  • __call__ 객체: 클래스 인스턴스가 속성으로 상태를 저장하면서 함수처럼 호출 가능
    (둘 다 “상태 + 호출” 패턴이지만, 저장 위치가 다름: 자유 변수 vs 인스턴스 속성)

 

정리하면

 

이 예제처럼 클로저를 쓰면 간단한 상태 유지형 함수를 쉽게 만들 수 있고,
co_freevars, __closure__를 이용하면 어떤 변수를 캡처했고 값이 어떻게 변했는지까지 투명하게 확인할 수 있습니다.