본문 바로가기

python

클로저(closure)

 

클로저(closure)

함수안에 또 다른 함수가 선언되어 반환되는 것을 클로저 함수라고 한다. 
  - 전역변수를 사용하지 않고 지역변수를 함수 밖에서 계속 참조 가능
  - 내부 데이터의 은닉에 활용
  - 객체 처리 효과 가능


파이썬에서 클로저를 만들기 위한 조건
   -. 중첩 함수(Nested Function)를 갖는다.
   -. 중첩 함수는 자신을 감싸고 있는 함수 영역(부모함수)의 변수를 참조하고 있다.
   -. 부모함수는 중첩 함수(자식 함수)를 반환한다.

 

 

클로저를 사용하지 않은 코드

클로저를 사용하지 않는 경우 out()함수를 실행할때마다 부모함수의 변수인 count=0을 참조하기 때문에 몇번을 반복하던 print(out())는 1이 출력된다

print('클로저를 사용하지 않은 경우---')
#count = 0
def out():
    count = 0
    def inn():
        nonlocal count
        count +=1
        return count
    # print(inn()) 아래 식과 같다
    imsi = inn()
    return imsi
    
#out()
#out()
print(out())
print(out())

클로저를 사용하지 않은 경우---
1
1

 

 

클로저를 사용한 코드

먼저 print(var1)은 outer() 함수를 실행하지만 내부함수 inner의 주소값만 반환하고 실행하지 않는다. 따라서 print(var1)로 출력되는 값은 count의 값이 아닌 내부함수의 inner 주소이다.

반면 print(var1())은 outer()함수 안의 inner()함수를 실행해서 inner()함수 안에 저장된 count 값을 print()로 출력한다.

클로저를 사용하지 않은 코드와 다르게 inner()함수 안의 count 값을 사용함으로 부모함수의 변수 식인 count =0이 반영되지 않고  출력할 때마다 count 값이 늘어난다.

print('\n클로저를 사용한 경우 ---')
def outer():
    count = 0
    def inner():
        nonlocal count
        count +=1
        return count
    return inner # <=== 클로저 : 내부함수의 주소를 반환

var1 = outer()
print(var1)
print(var1())
print(var1())
print(var1())

클로저를 사용한 경우 ---
<function outer.<locals>.inner at 0x000001B822E333A0>
1
2
3

 

 

클로저 활용 예시 - 수량 * 단가 * 세금을 계산하는 함수 만들기

print('*** 수량 * 단가 * 세금을 계산하는 함수 만들기')
# 분기별로 세금은 동적이다.
def outer2(tax):
    def inner2(su, dan):
        amount = su * dan * tax
        return amount
    return inner2

# 1분기에는 tax가 0.1 부과
q1 = outer2(0.1)
result1 = q1(5, 50000)
print('result1 : ', result1)
result2 = q1(1, 10000)
print('result2 : ', result2)
    
# 2분기에는 tax가 0.05 부과
q2 = outer2(0.05)
result3 = q2(5, 50000)
print('result3 : ', result3)
result4 = q2(1, 10000)
print('result4 : ', result4)

*** 수량 * 단가 * 세금을 계산하는 함수 만들기
result1 :  25000.0
result2 :  1000.0
result3 :  12500.0
result4 :  500.0