Programming/Python

함수 데코레이터와 클로저

True or False 2023. 6. 12. 10:24

함수 데코레이터는 소스 코드에 있는 함수를 표시해서 함수의 작동을 개선할 수 있게 해준다.

데코레이터 ⇒ 다른 함수를 인수로 받는 콜러블 이다.

 

@decorate
def target():
	print('running target()')

# 위 코드와 아래 코드는 동일하게 동작

def target():
	print('running target()')

target = decorate(target)

데코레이터는 다른 함수를 인수로 전달해서 호출하는 일반적인 콜러블과 동일하다.

그렇지만 런타임에 프로그램 행위를 변경하는 메타프로그래밍을 할 때 데코레이터가 상당히 편리하다.

 

요약

  1. 데코레이트된 함수를 다른 함수로 대체하는 능력이 있다.
  2. 데코레이터는 모듈이 로딩될 때 바로 실행된다.(데코레이트는 임포트 타임에서 실행, 데코레이트 된 함수는 명시적으로 호출될 때 만 실행)
promos = []

def promotion(promo_func):
	promos.append(promo_func)
	return promo_func

@promotion
def fidelity(order):
	return ...

@promotion
def bulk_item(order):
	return ...

@promotion
def large_order(order):
	return ...

def best_promo(order):
	return max(promo(order) for promo in promos)

# 이렇게 할 경우 데코레이트 된 함수는 promos 에 등록이 되어있음 따로 추가하는 번거로움이 사라짐

 

b= 9

# 정상 동작
def f1(a):
	print(a)
	print(b)

f1(3)

b=9

# 에러 발생 : 이유 => 함수 실행시 print(b) 는 함수 내에 선언된 지역 변수를 참조
# 하지만 b=6 은 print(b) 보다 뒤에 선언되기 때문에 에러발생 globals()로 전역변수를 참조명시
def f2(a):
	print(a)
	print(b)
	b= 6

f2(3)

클로저 ⇒ 함수 본체에서 정의하지 않고 참조하는 비전역 변수를 포함한 확장 범위를 가진 함수다.

함수가 비전역 외부 변수를 다루는 경우는 그 함수가 다른 함수 안에 정의된 경우 뿐 이라는 점에 주의

 

숫자, 문자열, 튜플 등 불변형은 읽을 수만 있고 값은 갱신할 수 없다.

⇒ nonlocal 을 통해서 지역 변수임이 아닌 자유변수임을 명시한다.

 

functools.lru_cache() Least Recently Used 방식으로 최근 가장 오래 안쓰인 부분을 제거하는 방식으로 캐시 관리

 

functools.singledispatch() 로 데코레이트 하면 범용 함수가 된다. 자료형에 따라 서로 다른 방식의 연산을 수행하게 된다.