Closure

클로저 (Closure) 는 함수의 종류로,일반 함수와는 다르게 프리 변수 (free variable) 를 복사하고 저장한 뒤, 후에 액세스할 수 있게 도와준다.

예제 코드

def outer_func(): #1
    message = 'Hi' #3
 
    def inner_func(): #4
        print(message) #6
 
    return inner_func #5
 
my_func = outer_func() #2
my_func() #7
Hi
  • messageouter_func 의 변수다.
  • inner_func 는 해당 변수를 가져다 출력한다.

주석 #2 에서 확인할 수 있듯이 outer_func() 이 호출된 이후에는 message 는 지역 변수이므로 존재하지 않는다. 그럼에도 불구하고 주석 #7 에서 수행된 my_func() 에서 message 변수를 사용할 수 있는 이유는 inner_func 이 클로저 함수이고, message 함수를 따로 저장하였기 때문이다.

그렇다면 도대체 클로저 함수는 어디다가 변수를 저장하는 것인가? 해답은 __closure__ 라는 매직 메소드에 존재한다. __closure__ 라는 메소드는 cell 이라는 tuple 타입을 반환하는데, 이 cellcell_contents 안에는 message 변수의 값이 포함되어 있다.

print(my_func)
print(dir(my_func))
print(type(my_func.__closure__)) #9
print(my_func.__closure__)  #10
print(my_func.__closure__[0])  #11
print(dir(my_func.__closure__[0]))  #12
print(my_func.__closure__[0].cell_contents)  #13
# print(my_func)
<function inner_func at 0x1019dfed8>	
 
# print(dir(my_func))
['__call__', '__class__', '__closure__', '__code__', '__defaults__', 
	'__delattr__', '__dict__', '__doc__', '__format__', '__get__', 
	'__getattribute__', '__globals__', '__hash__', '__init__', '__module__', 
	'__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
	'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 
	'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 
	'func_name']
 
# print(my_func.__closure__)
<type 'tuple'> 
 
# print(my_func.__closure__)
(<cell at 0x1019e14b0: str object at 0x1019ea788>,)
 
# print(my_func.__closure__[0])
<cell at 0x1019e14b0: str object at 0x1019ea788>
 
#  print(dir(my_func.__closure__[0]))
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', 
	'__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',
	 '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
	 '__subclasshook__', 'cell_contents']
 
# print(my_func.__closure__[0].cell_contents)
Hi

Related

References