코드를 반복하는 행위를 줄여야 하는데, 그 방법은 등록 데커레이터를 사용하는 것이다.
promos = []
def promotion(promo_func):
promos.append(promo_func)
return promo_func
@promotion
def fidelity(order):
"""충성도 포인트가 1000점 이상인 고객에게 전체 5% 할인 적용"""
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
@promotion
def bulk_item(order):
"""20개 이상의 동일 상품을 구입하면 10% 할인 적용"""
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() *.1
return discount
@promotion
def large_order(order):
"""10종류 이상의 상품을 구입하면 전체 7% 할인 적용"""
distinct_items = {item.product for item in order.cart}
if len(distinct_item) >= 10:
return order.total() *.07
return 0
def best_promo(order):
"""최대로 할인 받을 금액 반환"""
return max(promo(order) for promo in promos)
프로모션 전략 함수명이 특별한 형태로 되어 있을 필요 없고, @promotion 데커레이터는 데커레이터된 함수의 목적을 명확히 알려주며, 임시로 어떤 프로모션을 배저할 수 있지만 주석처리 필수.
프로모션 할인 전략을 구현한 함수는 @promotion 데커레이터가 적용되는 한 어느 모듈에서든 정의할 수 있다.
대부분의 데커레이터는 데커리이트된 함수를 변경하고, 내부 함수를 정의하여 그것을 반환하여 데커레이터된 함수를 대체하고, 내부 함수를 사용하는 코드는 제대로 동작하기 위해서 거의 항상 클로저에 의존하고, 이를 이해하기 위해서 파이썬에서 변수 범위의 작동 방식 생각하기