파이썬은 데코레이터라는 기능을 제공한다.
데코레이터는 말 그대로 장식이라는 뜻을 가지고 있다.
함수 위에 @
로 시작하는것이 데코레이터 이다.
decorator 란 무엇이며 언제 왜 사용하는것일까 ?
def jackpot_stock_information():
return "계시가 내려졌습니다. 삼성전자를 사세요!"
이 주식정보는 유료회원만 받을 수 있다.
그래서 이 함수가 호출 되기 전에 해당 유저가 유료회원인지를 확인해야 한다.
그리고 해당 유저가 유로 회원인지 확인 해주는 함수는 다음과 같다 .
일단은 모든 유저가 유료 회원이라고 가정을 해본다.
def is_paid_user():
return True
jackpot_stock_information 함수가 호출되기 전에 is_paid_user 함수가 호출되어야 확인이 가능하다.
if is_paid_user():
jackpot_stock_information()
이렇게 is_paid_user
함수 상단에 jackpot_stock_infomation()
를 호출하게 되면 문제가 없어 보인다.
하지만 만약에 다른곳에서 사용을 해야한다면 ??
jackpot_stock_information 함수가 호출 될때 is_paid_user 가 무조건 먼저 되어야 하는데 , 그럼
jackpot_stock_information 함수를 호출할때 마다 똑같이 is_paid_user 함수를 호출해야한다.
그래서 jackpot_stock_information 함수를 호출할 때 알아서 자동으로 is_paid_user 함수가 강제적
으로 먼저 호출되게 할 수 있는 방법이 없을까 ?? 라는 생각이 들었다. ==> decorator
@is_paid_user
def jackpot_stock_information():
return "계시가 내려졌습니다. 삼성전자를 사세요!"
위의 골뱅이로 장식 을 해주면 된다.
jackpot_stock_information 함수가 호출되기 전에
is_paid_user 함수가 호출하게 된다.
그렇다면 아무함수에 다 decorator 를 달아버리면 되지않나 ??
그렇게는 안됩니다.
decorator로 장식할 수 있는 함수는 중첩 함수 (nested function)을 리턴하는 함수만 decorator 함수로 사용 될 수 있다.
decorator 함수의 기능을 다르게 설명하면 chain of functions 라고 설명할 수 있다.
여러개의 함수가 연속적으로 호출이 자동으로 되게 해주는것이다.
그럴려면 마지막 함수를 제외한 함수들은 그 다음 함수를 리턴해줘야 파이썬이 함수들을 차례대로 호출 해줄수 있겠지 ??
(만일 다음 함수를 리턴하지 않고 다른 값을 리턴해버리면 그다음 함수로 넘어가지 못하고 그냥 함수 실행이 종료된다 )
위 그림처럼 마지막 함수를 제외한 함수들은 그다음 함수를 리턴을 해줘야한다.
def is_paid_user(func):
user_paid = True # 간단화 하기 위해 무조건 True
def wrapper(*args, **kwargs):
if user_paid:
return func()
else:
return
return wrapper
@is_paid_user
def jackpot_stock_information():
return "계시가 내려졌습니다. 삼성전자를 사세요!"
print(jackpot_stock_information())
📌👉
https://dojang.io/mod/page/view.php?id=2428
위는 매개변수가 없이 데코레이터를 만들었다면 ,
지금부터는 매개변수
와 반환값
을 처리하는 데코레이터를 보기로 한다.
def trace(func):
def wrapper(a,b):
r = func(a,b)
print(f'{func.__name__} , {a} , {b}')
return r
return wrapper
@trace
def add(a,b):
return a+b
print(add(10,20))
위의 코드 def add(a,b):
는 매개변수의 개수가 고정된 함수이다.
매개변수(인수)가 고정되지 않은 함수는 어떻게 처리할까?
wrapper
함수를 가변 인수 함수로 만든다.
def trace(func): # 호출할 함수를 매개변수로 받음
def wrapper(*args, **kwargs): # 가변 인수 함수로 만듦
r = func(*args, **kwargs) # func에 args, kwargs를 언패킹하여 넣어줌
print('{0}(args={1}, kwargs={2}) -> {3}'.format(func.__name__, args, kwargs, r))
# 매개변수와 반환값 출력
return r # func의 반환값을 반환
return wrapper # wrapper 함수 반환
@trace # @데코레이터
def get_max(*args): # 위치 인수를 사용하는 가변 인수 함수
return max(args)
@trace # @데코레이터
def get_min(**kwargs): # 키워드 인수를 사용하는 가변 인수 함수
return min(kwargs.values())
print(get_max(10, 20))
print(get_min(x=10, y=20, z=30))