(Python) 클로저란 with 일급객체
클로저를 알기위해서는 파이썬의 함수 특징에 대해 알아야 한다
일급객체란
변수 or 데이터 구조(자료구조) 안에 담을 수 있어야 한다
함수의 매개변수로 전달할 수 있어야한다
함수의 결과 반환값으로 사용될수 있어야 한다
실행시점에 초기화된다(런타임 초기화)
파이썬에서 함수는 일급 객체의 조건을 모두 만족한다. 함수를 변수에 할당할 수 있고, 인자로 전달이 가능하며, 함수의 리턴값으로도 사용될 수 있다
1. 함수가 변수로 할당
def factorial(n):
"""
Factorial function -> n : int
"""
if n == 1:
return 1
return n * factorial(n - 1)
var_func = factorial # 변수에 할당(함수를 변수에 할당하여 사용할 수 있다)
print(var_func) # <function factorial at 0x7fc10e385620> factorial함수가 할당됨을 알 수 있다
print(var_func(20))
print(list(map(var_func, range(1,5)))) # [1, 2, 6, 24]
2. 함수가 다른 함수의 매개변수로 사용
def factorial(n):
"""
Factorial function -> n : int
"""
if n == 1:
return 1
return n * factorial(n - 1)
var_func = factorial
print(list(map(var_func, filter(lambda x: x % 2, range(1, 6))))) # var_func가 filter함수의 인자로 전달
3. 함수가 리턴값으로 사용
def factorial():
def result():
print('this factorial function')
return result # 함수값이 리턴됨
var_func = factorial()
var_func()
클로저(Closure)란
클로저는 어떤 함수의 내부 함수가 외부 함수의 변수를 참조할때 외부 함수가 종료된 후에도 내부 함수가 외부 함수의 변수를 참조할 수 있도록 어딘가에 저장하는 함수를 말한다. 즉 외부에서 호출된 함수의 변수값, 상태(레퍼런스) 를 복사 후 어딘가 저장한 다음 접근(액세스) 가능할 수 있게 도와준다
함수의 내부함수
내부 함수가 외부 함수의 변수를 참조
외부 함수가 내부 함수를 리턴
# closure 사용
def closure_ex1():
# free variable : 어떤 함수에서 사용되지만 그 함수 내부에서 선언되지 않은 변수, 즉 지역도 전역도 아닌 변수
# 클로저 영역
series = [] # free variable로 self._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) # <function closure_ex1.<locals>.averager at 0x7f368c2078c8>
print(avg_closure1(10))
print(avg_closure1(20))
closure_ex1함수의 역할이 끝나면 series도 소멸되어야 하지만 중첩 함수인 averager의 외부 함수인 closure_ex1의 변수 Series와 averager의 환경을 저장하는 클로저가 생성된다. 클로저는 dir을 통해 저장된 위치 등을 알 수 있다
print(dir(avg_closure1))
print()
print(dir(avg_closure1.__code__))
print(avg_closure1.__code__.co_freevars) # ('series',) free variable 즉, 자유변수가 소멸되지 않고 저장되는 공간이다.
print(avg_closure1.__closure__[0].cell_contents) # 클로저가 저장 되는 경로라고 보면 된다