def test_decorator(func):
def wrapper():
func()
return wapper
def test():
print("run test func")
deco = test_decorator(test)
deco()
# test
# run test func
'''
@데코레이터
def 함수이름():
코드
'''
def test_decorator(func):
def wrapper():
print(func.__name__)
func()
return wrapper
@test_decorator
def test():
print("run test func")
test()
# test
# run test func
def test_deco1(func):
def wrapper():
print("test_deco1")
func()
return wrapper
def test_deco2(func):
def wrapper():
print("test_deco2")
func()
return wrapper
@test_deco1
@test_deco2
def test():
print("run test()")
test()
deco = test_deco1(test_deco2(test))
deco()
def trace(func):
def wrapper(a, b):
r = func(a, b)
return r
return wrapper
@trace
def add(a, b):
return a + b
print(add(10, 20)) # 30
def trace(func):
def wrapper(a, b):
r = func(a, b)
return r * 10
return wrapper
@trace
def add(a, b):
return a + b
print(add(10, 20)) # 300
def trace1(func):
def wrapper(a, b):
print("trace1")
return func(a, b) + 12
return wrapper
def trace2(func):
def wrapper(a, b):
print("trace2")
return func(a, b) + 14
return wrapper
@trace1
@trace2
def add(a, b):
return a + b
print(add(10, 20))
# trace1
# trace2
# 56
@trace1
@trace2
def add(a, b):
return a + b
print(add(10, 20))
# trace2
# trace1
# 56
def trace(func):
def wrapper(*args, **kwargs):
pass
return wrapper()
def test_deco(x):
def real_deco(func):
def wrapper(a, b):
print(x)
func(a, b)
return wrapper
return real_deco
@test_deco("test_deco_parameter")
def test(a, b):
print(a, b)
test(1, 2)
# test_deco_parameter
# 1, 2
데코레이터를 여러 개 사용하면, 데코레이터에서 반환된 wrapper 함수가 다른 데코레이터로 들어간다.
따라서 함수의 __name__ 을 출력해보면 wrapper 가 나온다.
이 때는 fuctools 모듈의 wraps 데코레이터를 사용해야 한다.
import functools
def test_deco(x):
def real_decorator(func):
@functools.wraps(func)
def wrapper(a, b):
print(func.__name__)
print("x: " + str(x))
return a + b
return wrapper
return real_decorator
@test_deco(1)
@test_deco(2)
def add(a, b):
return a + b
print(add(10, 20))
class Trace:
def __init__(self, func): # 호출할 함수를 인스턴스의 초깃값으로 받음
self.func = func # 호출할 함수를 속성 func에 저장
def __call__(self):
print(self.func.__name__, '함수 시작') # __name__으로 함수 이름 출력
self.func() # 속성 func에 저장된 함수를 호출
print(self.func.__name__, '함수 끝')
@Trace # @데코레이터
def hello():
print('hello')
hello() # 함수를 그대로 호출
class TestDeco:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
r = self.func(*args)
print(r)
print(self.func.__name__)
return r
@TestDeco
def test(a, b):
return a + b
test(1, 2)
class TestDeco:
def __init__(self, x):
self.x = x
def __call__(self, func):
def wrapper(a, b):
print(a, b)
r = func(a, b)
print(r)
return r + self.x
return wrapper
@TestDeco(3)
def test(a, b):
return a + b
print(test(1, 2))
# 1, 2
# 3
# 6
참고자료: 코딩도장: 데코레이터