본문 바로가기
목차
Python

[Python] Closure

by ds31x 2023. 7. 15.
728x90
반응형

https://sleebapaul.github.io/python-decorators/

Closuer의 정의

Closure의 정의는 다음과 같음.

 

Nested function 으로,
자신의 enclosing scope (= Python에서 non-local scope)의 상태값
(lexcical environment의 variable 값, outer context)을

기억하고 유지, 변경, 사용할 수 있는 high-order function를 가르킴.

2024.11.20 - [Python] - [Py] High-order Function (고차함수)

 

[Py] Higher-order Function (고차함수)

정의 : Higher-order function(고차 함수)란, 다음 조건 중 하나 이상을 충족하는 function를 가리킴:다른 함수를 argument로 받을 수 있는 function다른 함수를 반환할 수 있는 function즉, Higher-order function이란 fu

ds31x.tistory.com


Closure의 특징

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와 같은 효과를 흉내낼 수 있게 해주는 등의 이점을 가진다.

 

즉, global variable(전역변수)의 기능을 활용하면서도 아무나 접근을 제한하면서 각 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을 꾸며주는 기능을 제공한다.Decorator를

ds31x.tistory.com


 

728x90