중첩함수, closure 와 decorator


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 

python을 작성할 때, global 변수는 최대한 사용하지 않는 것이 좋다. 모두가 접근 가능하므로 수정/삭제 등의 위험에 쉽게 노출되기 때문이다. 때문에, closure는 non-local 변수 등을 활용함으로써 데이터를 함수 안에 숨길 수 있다. class를 만들기 애매할 때(변수나 함수가 많지 않을 때) closure를 사용할 수도 있다.

그리고 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 속성을 가진 함수는

  • 선언한 변수에 할당할 수 있다 (변수값).
  • 다른 함수의 parameter로 전달될 수 있다.
  • 다른 함수의 return값으로 사용될 수 있다.
###############################
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)
profile
예비 개발자의 기술 블로그 | explore, explore and explore

0개의 댓글