0. Introudtion
Closure가 필요한 이유 그리고, 잘못 사용된 사례에 대해 알아보자.
1. UnboundLocalError
전역 변수와 지역 변수에 대해 간단히 복습해보자.
|
|
func_v3를 정의하기 전에 c에 값을 할당했다.
그래서 func_v3 안에 값은 이름의 c 와 이어질거라 생각했지만, Error가 떴다.
Error의 의미:
c
라는 변수에 값이 할당되지 않았는데, print(c)로 참조되었다.- 함수 블럭에서 할당하는 건
지역 변수
다. - 하지만, name이 같아도 함수 밖에서 할당했기 때문에
전역 변수
로 인식하여 다르다.
해결책
- function block 안에
global
선언을 하든가,nonlocal
선언을 한다. - local scope에서 전역으로 쓸 수 있는 방법이다.
- function block 안에
|
|
해결책의 문제점
- 함수 내에
global
또는nonlocal
을 쓰는 건 좋은 방법이 아니다. - 왜냐하면 함수 내에 전역 변수와 연결되는 게 있다면 디버깅 할 때 쉽지 않다.
- 그래서 위의 statement로 local에서 수정하는 건 권하지 않는다.
- 함수 내에
그래서 또 다른 방법이 바로
closure(클로저)
다.이 클로저에 대해 알아보자.
2. Closure
2.1 What is closure ??
Reference에 따른 closure 정의: 외부에서 호출된 함수의 변수값, 상태(레퍼런스)를 복사 후 저장한다. 그 후에 접근(액세스)이 가능하도록 하는 도구
나만의 정의: 함수가 선언될 당시의 상황을 기억(closure: 포섭)했다가, 차후 호출될 때 기억한 환경을 사용하는 함수
scope을 기준으로 설명하자면
Closure란 enclosing scope에 있는 자유변수(free variable)를 이 scope의 실행이 종료되도 보유하고 있는 내부 함수 또는 중첩함수를 말한다.
자유변수(free variable)란??
- 정의되지 않은 code block에 사용되는 변수
- 여러 번 호출이 일어나도 상태 정보를 보유하기 위해 closure가 사용하는 원리
closure는 outer function을 호출해서 inner function을 return 했지만, inner function의 enclosing scope 에 있던 자유변수(free variable)를 계속해서 기억한다.
그래서, 함수실행이 끝나도 그 시점의 변수를 이어서 작업할 수 있다.
2.2 Why does we need closure ??
함수 안에 선언된 것들이 함수의 실행이 끝나서 소멸되면 변수 값도 사라지지만, closure를 사용하면 기억되기 때문에, single thread여도 동시성 제어가 가능하다.
서버 프로그래밍의 관점에서 closure를 바라보면
- 서버 프로그래밍에서 어려운 것이
동시성(Concurrency) 제어
다. - 한정된 메모리 공간에서 여러 자원이 접근하면
교착상태(Dead lock)
에 부딪힌다. - 이를 해결하는 게
동시성(Concurrency) 제어
다. - closure는 불변자료 (immutable, Read Only) 구조 및 atom, STM 이므로 multi-thread 프로그래밍에 강점을 가진다.
- multi-thread가 아닌 단일 thread 인데도 동시성을 갖도록 하는 기반이 되는 게 바로 closure다.
- 서버 프로그래밍에서 어려운 것이
또한, 이 클로저는 함수형 프로그래밍에도 연결된다.
그러면 class를 사용하여 closure가 무엇인지 구현해보자.
|
|
위의 예시처럼 class 실행이 끝나서, 변수가 소멸되야하는데 유지되고 있다. 상태를 기억하고 있기 때문에 계속해서 누적된다. 그래서 중간부터 해도 이어서 할 수 있다.
3. Exercises for closure
closure는 pattern이 정해져 있다.
|
|
- series가 local scope에 있었다면 위 경우처럼 출력할 때 이전 값이 보존되지 않는다.
- 왜냐하면 averager가 실행이 끝나면 그 안에 local scope에 있던 변수는 소멸된다.
- 하지만, enclosing scope에 변수를 정의했기 때문에, 함수를 실행할 때마다 자유변수에 접근해서 값이 보존된다.
- 그래서 새로 추가해도 실행이 가능하다.
- 그러면 파이썬에서 이 closure를 어떻게 취급하는지 확인해보자.
|
|
__code__
: 함수가 컴파일되서 바이트코드 상태의 정보를 출력해주는 역할
4. Incorrect use of closures
- closure의 잘못된 사용법을 예제로 알아보자.
|
|
- 바로 위의 예시처럼
nonlocal
을 사용하는 방법 그리고, UnboundLocalError를 설명할 때 언급한global
을 사용하는 법이 잘못된 closure 사용법이다. - UnboundLocalError 를 설명한 경우와 달리, 변수를 전역이 아닌 자유 변수로 만들었고, 내장 함수를 반환했기 때문에 closure지만 좋은 방법이 아니다.
- 왜냐하면 함수 내에 지역 변수 외의 것과 연결되는 게 있다면 디버깅 할 때 쉽지 않다.