11.클로저(Closure)
by SANGGI JEON
클로저(Closure)
- First class function을 지원하는 언어의 네임 바인딩 기술
- 어떤 함수를 함수 자신이 가지고 있는 환경과 함께 저장한 레코드
- 클로저는 함수의 지역 변수 값을 그 함수가 종료된 후에도 기억
- 함수가 가진 프리변수(Free Variable)를 클로저가 만들어지는 당시의 값과 레퍼런스에 매핑하는 역할
- 프리변수(Free Variable) : 코드블럭 안에서 사용은 되지만 코드블럭안에서 정의 되지 않은 변수
- 자신의 영역 밖에서 호출된 함수의 변수값과 레퍼런스를 복사하고 저장
- 함수가 종료된 이후에도 참조가 가능한 것을 클로저(Closure)라고 함
# 예제 1
import time
def log_formatter(msg):
def log_message():
time_str = time.strftime('%c', time.localtime(time.time()))
print(time_str, end='')
print('------>', end='')
print(msg) # MSG는 프리변수
return log_message
log_msg = log_formatter('test log')
print(log_msg)
log_msg()
del log_formatter
try:
print(log_formatter)
except NameError:
print('log_formatter 함수는 존재하지 않습니다.')
log_msg()
msg는 log_formatter 함수가 종료되면 사라지는 Local namespace의 변수이다. 하지만 log_message를 클로저로 활용하여 함수가 종료된 이후에도 msg의 값을 출력할 수 있다.
# 예제 2
def outer_func():
msg = 'Good Morning!'
def inner_func():
print(msg)
return inner_func
func = outer_func()
print(func)
print(dir(func)) # dir(): 객체로 사용할 수 있는 멤버를 알려 줌
print(type(func.__closure__)) # closure의 type이 tuple인 것을 확인
print(func.__closure__) # closure는 cell 객체로 이루어짐
print(func.__closure__[0].cell_contents) # cell_contents로 값을 확인
# 결과
<function outer_func.<locals>.inner_func at 0x000002A8ABB61948>
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
<class 'tuple'>
(<cell at 0x000002A8ABA399D8: str object at 0x000002A8ABA4D9F0>,)
Good Morning!
dir(func)을 통해서 func에서 객체로 사용할 수 있는 멤버에서 clouser가 있다는 것을 알 수 있다. func.__ closuer __의 타입이 tuplue이고 요소가 한개 인것을 알 수 있다.
그리고, func.__ clouser __의 0번째 요소의 cell_contents를 통해 클로저의 값을 확인 할 수 있다.
Subscribe via RSS