개인 공부 후 자료를 남기기 위한 목적이므로 내용 상에 오류가 있을 수 있습니다.
1월 29일(토)
Closure
1. Nested Function
- 중첩함수는 함수로 감싸인 함수를 의미한다. (함수 안에 정의된 함수)
- Nested function은 개념적인 용어로, 함수 안에 정의된 함수는 Inner function이라고 표현한다.
- 그리고 Inner function를 감싸고 있는 외부함수를 Outer function이라고 한다.
- 각 내부 함수들은 Scope chain에 의해서 자신을 감싸고 있는 외부함수의 메모리에 접근할 수 있다.
- 좀 더 자세히 설명하면, 내부함수는 외부 함수가 가지고 있는 변수나 매개변수 등에 접근할 수 있고 사용할 수 있다는 의미이다.
- 이는 내부함수가 외부 함수의 메모리를 복사해서 가지고 있다는 의미이다.
(참고)
def calculator(x,y):
def add():
return x+y
def sub():
return x-y
return (add(), sub())
2. First-Class Function
- 파이썬에서 사용하는 여러 기술을 이해하기 위한 가장 기본적인 개념이 바로 'First-Class'이다.
- First-Class의 기본은 'first-class citizen'이라는 개념에 있다.
- 프로그래밍 언어에서 first-class citizen 속성을 가진다는 것은 어떤 객체를 다른 객체의 매개변수로 전달하거나, 함수의 반환값으로 사용하거나, 변수에 값으로 할당할 수 있다는 것을 의미한다.
- 즉, 객체(자료형 및 함수) 등을 그 자체 매개변수로 전달하거나 반환값으로 사용할 수 있으면 이는 first-class citizen 속성을 가진다고 말한다.
(참고)
def square(x):
return x*x
f = square # first-class citizen
f(10) # first-class function
3. Closure
- Closure는 중첩함수의 일종으로 개념상으로는 Nested function의 하위 개념이다.
- 사전적 정의로는 first-class function을 지원하는 언어에서 함수와 유효 범위의 이름을 바인딩하는 기술이다.
(함수와 함수가 사용하는 환경을 저장하는 것) - 즉, 외부함수의 반환값으로 내부함수를 반환하는 함수라고 정의할 수 있다.
- 참고로, 외부함수의 지역변수인 Non-local 변수가 존재하고 외부함수가 이미 종료되었어도 내부함수는 외부함수와 관련된 환경을 따로 저장하고 있기 때문에 Non-local 변수를 참고할 수 있다.
- 따라서, 클로저(Closure)는 함수와 함수가 사용하는 환경을 저장하는 개념이다.
(참고)
def multiple_of_ten():
square_root = 10
def square(x):
return square_root ** x
return square
f = multiple_of_ten()
f(2)
f(3)
4. Closure를 사용하는 이유
- Global 변수를 사용하지 않고, Non-local 변수로 특정 데이터를 숨겨서(보호해서) 함수 기능을 사용하고자 할 때 주로 사용된다.
- 다루는 변수나 함수가 많지 않은 경우에는 클래스를 사용하는 것 보다 클로저를 사용하는 것이 더욱 효율적이다.
- 데코레이터를 사용할 때 주로 사용된다. (어떤 함수를 실행하기 전이나 실행하고 난 후에 특정 기능을 수행하기 위한 목적)
5. Closure 사용 시 주의할 점
- 클로저에서 외부함수의 변수인 Non-local 변수는 외부함수가 실행되는 시점에서 생성되고 복사되어 내부함수의 __Closure__ 속성에 저장된다.
- 이 때문에 클로저 사용 시, Non-local 변수로 시간과 관련된 값을 사용하게 되면 의도하지 않은 결과가 나타날 수 있다.
- 아래의 예시코드를 참고하면, 외부함수가 실행되는 시점에 datetime.now() 함수가 실행되고 해당 값이 __Closure__ 속성에 저장되기 때문에 내부함수에는 계속 동일한 시간값만 적용되는 것이다.
- 따라서 클로저를 구현할 때에는 Non-local 변수에 시간이나 흐름에 따라 변하는 값을 할당하지 않아야 한다.
(참고)
import datetime
import time
def logger():
now = datetime.datetime.now()
def print_log(message):
return f"{now}, {message}"
return print_log
logger = logger()
print(logger("start"))
time.sleep(10)
print(logger("After 10 sec")
'''
기대하는 결과 :
>> 2020-12-03 15:35:30, start
>> 2020-12-03 15:38:40, After 10 sec.
실제 결과 :
>> 2020-12-03 15:38:30.670492, start
>> 2020-12-03 15:38:30.670492, After 10 sec.
'''
'기타' 카테고리의 다른 글
TIL - 22.01.31 (0) | 2022.01.31 |
---|---|
TIL - 22.01.30 (0) | 2022.01.30 |
TIL - 22.01.28 (0) | 2022.01.29 |
TIL - 22.01.27 (0) | 2022.01.27 |
TIL - 22.01.26 (0) | 2022.01.26 |
댓글