Python decorator / meta data (@wraps(func) /

jaeha_lee·2022년 5월 4일
0

Decorator

기존에 있는 코드에 기능을 추가할 때,
이름과 사용법을 동일하게 유지하면서 기능을 추가하기 위해


def origin(func):
	def wrapper(): # wrapper 이 부분의 이름은 자유롭게
    	print("Origin Func")
        func()
    return wrapper
    
def copy1():
	print("Copy1 Func")

@origin
def copy2():
	print("Copy2 Func")
   
 # "Origin Func Copy1 Func" 함수 호출 한번으로 2개의 함수 동시에 실행
 copy1 = origin(copy1) # 이렇게 하는 방법이 있고
 
 copy1()
 copy2()
    
# 여기서 wrapper는 모든 인자를 받을 수 있어야 함. 즉, wrapper에서 사용하고자 하는 함수에는 인자가 모두 들어가 있어야 함.
# 그래서 본 예시에서는 copy3 가 인자 x를 받기 때문에 wrapper에서 *args,**kwargs를 표기
# 예시
def origin2(func):
	def wrapper(*args,**kwargs):
    	print("Origin2 Func")
        result = func(*args.**kwargs)
    return wrapper
    
@orgigin2    
def copy3(x):
	print(f"copy 3 Func. Parameter = x")
    

cf) 함수의 실행 시간을 알고 싶을 때 decorator를 사용하면 쉽게 가능

from functools import wraps
def func_time(func):
	@wraps(func) # func 데이터를 다 가지고 있음. 이렇게 하면 
    # func에 대한 __name__, __doc__ 다 접근 가능
    # 메타데이터를 유지
    def wrapper(*args,**kwargs):
    	start = time.time()
    	result = func(*args,**kwargs)
        end = time.time()
        print(f"elapsed time : {end-start}")
        return result
     return wrapper        
cf) 함수의 호출 횟수와 해당 함수의 변수 메모리를 다르게 쓰는 방법 (nonlocal)
def parent(func):
    num = 0
    @wraps(func) # func 데이터를 다 가지고 있음. 이렇게 하면 
    # func에 대한 __name__, __doc__ 다 접근 가능
    # 메타데이터를 유지
    def wrapper(*args,**kwargs):
        nonlocal num
        num+=1
        print(f"{func.__name__} called {num} times")
        return func(*args,**kwargs)
    return wrapper 
#
@parent # test1 = parent(test1)
def test1(a,b):pass
@parent
def test2(a,b):pass
test1(1,2)
test2(2,3)
test1(4,5)
test1(4,5)
test1(4,5)
test2(2,3)
test2(2,3)
test1(4,5)
"""
출력 결과
test1 called 1 times
test2 called 1 times
test1 called 2 times
test1 called 3 times
test1 called 4 times
test2 called 2 times
test2 called 3 times
test1 called 5 times
"""
Decorator에 인자 보내기! => 한번더 감싸주면 됨
def parent(input_ = "Decorator")
	def decorator(func):
  	@wraps(func)
      def wrapper(*args,**kwargs):
      	print(input_)
          return func(*args,**kwargs)
      return wrapper
	return decorator
@parent("Decorator2")
def child(str_)"
	print(f"child, {str_}")
child("test")
print()
 @parent
def child(str_)"
	print(f"child, {str_}")
child("test")
"""
출력 결과
Decorator2
child test
Decorator
child test
"""



0개의 댓글