closure의 개념을 이해하려면 중첩함수부터 정리할 필요가 있겠다.
중첩함수는 함수 안에 함수가 있는 형태로, 외부함수+내부함수의 조합이다. 그리고 모든 내부함수는 외부함수의 메모리에 접근할 수 있다.
이 말은 즉 외부함수에서 갖고 있는 변수를 내부함수가 사용할 수 있다는 뜻이고, 외부함수의 메모리를 복사해서 소유한다는 의미이기도 하다.
closure는 외부함수의 return값이 내부함수인 함수를 뜻하며, 중첩함수의 하위 개념이다. closure는 해당 함수의 환경을 저장하기 때문에, 외부함수가 종료되었어도 내부함수 및 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()
print(f(2))
>100
그리고 decorator 작성 시 closure가 사용된다.
기존의 클래스나 함수를 수정하지 않고, 기능을 덧붙일 수 있는 문법을 말한다.
decorator는, 함수(func)를 argument로 받는 closure를 작성하고 그 함수를 안에서 구현하면 된다. 다른 값이 아닌 내부 함수를 반환하기 때문에, 전체 함수가 그냥 종료되지 않고 내부 함수를 실행할 수 있게 된다.
def deco(func):
def wrapper():
print("before")
ret = func()
print("after")
return ret
return wrapper
@deco
def base():
print("base func")
print(base())
> before
> base func
> after
> None
replit - decorator 문제의 답은 아래와 같다.
def welcome_decorator(func):
def new_greeting():
return func() + "welcome to WECODE!"
return new_greeting
@welcome_decorator
def greeting():
return "Hello, "
print(greeting())
>"Hello, welcome to WECODE!"
📌first-class function (일급 함수)
일급 함수는 first-class citizen 속성을 가지는 함수를 말한다. first-class citizen 속성을 가진 함수는
###############################
def square(x):
return x*x
f = square #변수 f에 함수 square 할당
print(f(10))
> 100
###############################
def square(x):
return x*x
def bind(func, arg_list): #함수 square를 매개변수로 넘김
result = []
for arg in arg_list:
result.append(func(arg))
return result
new_result = bind(square,[1,2,3])
print(new_result)
> [1,4,9]
###############################
def log(msg):
def log_message():
print("log: ", msg)
return log_message() #log_message함수를 return
log_hi = log("Hello Everybody")
print(log_hi)