파이썬에서는 아래와 같이 함수 안에 함수를 선언할 수 있습니다.
def outside():
def inside():
pass
그런데 이때 함수 inside
에서는 함수 outside
에 있는 변수에도 접근할 수 있습니다.
def outside():
n = 1
def inside():
print(n) # 1
이렇게 함수 inside
가 함수 outside
에 있는 변수에 접근할 수 있을 때 클로저 closure 라고 부릅니다.
클로저를 이용하면 데코레이터나 partial apply 된 함수를 만들기 편리합니다.
저번에 만든 maybe
데코레이터를 다시 보겠습니다.
def maybe(f):
def wrapper(x):
if x is not None:
return f(x)
return wrapper
위 코드를 보면 함수 wrapper
에서 바깥에 있는 함수인 maybe
의 인자 f
를 가져다 쓰는 것을 볼 수 있습니다.
함수 wrapper
가 함수 안에 있는 함수이고 클로저이기 때문에 가능합니다.
우리는 자동차 엔진의 구조나 원리를 정확히 몰라도 운전하는 법만 알면 운전을 잘 할 수 있습니다.
사람들마다 관심의 대상과 정도가 다르고 도구를 활용하는 목적이 다릅니다.
따라서 어느 수준까지 알아야 하는지는 개인이 판단하면 되겠습니다.
자동자 엔진의 구조가 궁금한 사람은 깊게 공부를 하면 됩니다.
그저 운전이 좋은 사람은 엔진 공부를 할 필요가 없습니다.
운전이 싫은 사람은 택시를 타도 됩니다.
차가 싫은 사람은 지하철을 타도 됩니다.
저 같이 자동자 엔진이 궁금하실 분들을 위해 더 적어봅니다.
파이썬에서 클로저를 구현한 원리는 아래와 같다고 합니다.
함수 객체 내부에
__closure__
속성을 만들고 여기에 필요한 값을 저장
위에서와 같이 간단한 클로저를 만들어봅니다.
def outside():
n = 1
def inside():
print(n)
return inside
여기에서는 확인을 위해 함수 outside
가 함수 inside
를 리턴하도록 했습니다.
클로저 함수는 아래와 같이 __closure__
라는 타입이 튜플인 값을 가지게 됩니다.
>>> f = outside()
>>> type(f.__closure__)
<class 'tuple'>
그리고 이 튜플 안에는 타입이 cell
인 값들이 저장되어 있고 이 타입은 cell_contents
라는 값을 가지고 있습니다. outside
가 가지고 있던 변수 n
의 값인 1
이 바로 여기에 저장되어 있습니다.
>>> type(f.__closure__[0])
class 'cell'
>>> f.__closure__[0].cell_contents
1