Closure의 정의는 다음과 같음.
Nested function 으로, 자신의 enclosing scope (= Python에서 non-local scope)의 상태값(lexcical environment의 variable 값)을 기억하고 유지, 변경, 사용할 수 있는 경우를 가르킴.
- 2023.07.15 - [Python] - [Python] Nested Function
- 2023.07.15 - [Python] - [Python] scope와 키워드 global, nonlocal
Closure가 되기 위해선
- 우선 nested function이어야 하고,
- 해당 nested function 내에서 nonlocal scope의 변수를 참조하여 사용해야하며,
- 해당 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' 카테고리의 다른 글
[Python] Boolean Operators, Relational Operators, and Membership Operator (0) | 2023.07.28 |
---|---|
[Python] List's methods (0) | 2023.07.17 |
[Python] scope와 키워드 global, nonlocal (0) | 2023.07.15 |
[Python] Nested Function (0) | 2023.07.15 |
[Python] first-class object (일급객체) (0) | 2023.07.15 |