본문 바로가기
Python

[Python] Closure

by ds31x 2023. 7. 15.

Closure의 정의는 다음과 같음.

 

Nested function 으로, 자신의 enclosing scope (= Python에서 non-local scope)의 상태값(lexcical environment의 variable 값)을 기억하고 유지, 변경, 사용할 수 있는 경우를 가르킴.


Closure가 되기 위해선

  1. 우선 nested function이어야 하고,
  2. 해당 nested function 내에서 nonlocal scope의 변수를 참조하여 사용해야하며,
  3. 해당 nested function에 대한 reference가 반환되어 이 후로 사용가능해야 한다.

Closure는
다른 모든 scope에서 접근 가능한 global variable 을 사용하는 대신에,
접근을 할 수 있는 함수를 특정 nested function으로 제한하면서도
global variable과 같이 한번의 함수 호출 이후에도 값을 유지하면서 계속적인 접근을 가능하게 해준다.

 

이를 통해

  • global variable의 남용을 막을 수 있고,
  • Java나 C++등에서의 private method와 같은 효과를 흉내낼 수 있게 해주는 등의 이점을 가진다.

 

즉, 전역변수의 기능을 활용하면서도 아무나 접근을 제한하면서 각 clousre별로 고유의 상태를 유지할 수 있다.

Python3.x에서
Clouser가 참조하고 있는 enclosing scope의 variable들을 item으로 가지는 tuple 변수가 존재함. <clousre_name>.__closure__ 에 square bracket으로 참조된 순서(index)로 접근할 수 있음.
(즉, 직접 접근해서 수정이 가능하긴 하다.)


다음은 아래와 같은 기능을 가지는 closure를 만드는 예제임.

 

1. exponent(지수)를 closure를 생성할 때 enclosing scope로부터 받아오고 ,

2. 동시에 해당 clousre함수가 몇 번 호출되었는지를 카운트 하는 기능을 가짐.


def gen_closure(p):
    call_cnt = 0

    def _ds_power (b, return_cnt=False):
        nonlocal call_cnt
        call_cnt += 1
        ret = b**p
        if not return_cnt:
            return ret
        return ret,call_cnt

    return _ds_power

p2_func = gen_closure(2)
print(p2_func(10))

p3_func = gen_closure(3)
r, c_p3 = p3_func(10, True)
print(r)

r, c_p2 = p2_func(10, True)
print(f'10^2={r}')
print(f'power2 : call_cnt={c_p2}')
print(f'power3 : call_cnt={c_p3}')

for idx,c in enumerate(p3_func.__closure__):
    print(f"p3_func's enclsing variable[{idx}]:{c.cell_contents}")

 

결과는 다음과 같음.

> python test_closure.py
100
1000
10^2=100
power2 : call_cnt=2
power3 : call_cnt=1
p3_func's enclsing variable[0]:1
p3_func's enclsing variable[1]:3

 

개인적으로 많이 애용하는 Closure의 사용은 decorator와 함께 기존의 함수를 수정하지 않고 wrapper function으로 기존 함수들을 조합하여 사용하는 경우이다.

 

하지만 clousre도 가독성 측면에서는 그리 좋지는 않기 때문에 남용하는 건 좋지 않다.

물론 global varaible 남용보다는 훨씬 낫지만...

 

JavaScript에선 정말 많이 사용되는 것에 비해 Python에선 그렇게까지 많이 이용이 되는 거 같지 않다. 물론 JS가 능숙한 이들의 코드를 보면 정말 많이 사용되는 경우가 있다. 하지만 개인적으로 nested function은 그리 좋아하지 않는다.

같이 보면 좋은 자료들

2023.08.18 - [Python] - [Python] Decorator

 

[Python] Decorator

Python이 제공하는 Decorator는 기존의 function을 수정하지 않으면서 특정 처리를 추가할 수 있게 해주는 도구라고 할 수 있다. Decorate의 "꾸미다"라는 의미에 맞게 기존 function을 꾸며주는 기능을 제공

ds31x.tistory.com

 

728x90