파이썬 특수 문법(데코레이터, 이터레이터등) - . Closure function

17. Closure function

  • 함수와 해당 함수가 가지고 있는 데이터를 함께 복사, 저장해서 별도 함수로 활용하는 기법으로 First-class 함수와 동일
  • 외부 함수가 소멸되더라도, 외부 함수 안에 있는 로컬 변수 값과 중첩함수(내부함수)를 사용할 수 있는 기법
  • 지금까지 배운 언어의 맥락과는 뿌리가 다른 사고 - 함수형 프로그래밍에서부터 고안된 기법
  • 그래서 처음에 접하면 매우 이해하기 어려움, 예제 코드로 보면서 이해하자
In [45]:
def outer_func(num):
    # 중첩 함수에서 외부 함수의 변수에 접근 가능
    def inner_func():
        print(num)
        return '안녕'
    
    return inner_func                 # 중첩 함수 이름을 리턴합니다.
In [46]:
closure_func = outer_func(10)    # <--- First-class function
closure_func()            # <--- Closure 호출 
10
Out[46]:
'안녕'

예제 코드로 이해하는 closure

  • 위의 예제에서 closure_func이 바로 closure 임
  • closure_func = outer_func(10) 에서 outer_func 함수는 호출 종료
  • closure_func() 은 결국 inner_func 함수를 호출
  • outer_func(10) 호출 종료시 num 값은 없어졌으나, closure_func()에서 inner_func이 호출되면서 이전의 num값(10)을 사용함
In [23]:
del outer_func

심지어 outer_func 함수를 아예 삭제해버려도 fn(), 즉 inner_func() 와 num값(10)은 살아있음

In [28]:
closure_func()
10
Out[28]:
'inner_func'

언제 closure를 사용할까?

  • closure는 객체와 유사
  • 일반적으로 제공해야할 기능(method)이 적은 경우, closure를 사용하기도 함
  • 제공해야할 기능(method)가 많은 경우등은 class를 사용하여 구현
In [47]:
def calc_square(digit):
    return digit * digit

def calc_power_3(digit):
    return digit * digit * digit

def calc_quad(digit):
    return digit * digit * digit * digit
In [48]:
print (calc_square(2))
print (calc_power_3(2))
print (calc_quad(2))
4
8
16
In [49]:
def calc_power(n):
    def power(digit):
        return digit ** n
    return power
In [52]:
power2 = calc_power(2)
power3 = calc_power(3)
power4 = calc_power(4)
In [53]:
print (power2(2))
print (power3(2))
print (power4(2))
4
8
16
초간단 연습3
1에서 5까지 1승부터 5승까지 출력하기 (위 calc_power() 함수를 사용해서 list_data 리스트 변수에 1승부터 5승까지 계산 클로져 함수를 넣어서 사용)
In [56]:
list_data = list()
for num in range(1, 6):
    list_data.append(calc_power(num))

for func in list_data:
    print(func(2))
2
4
8
16
32