6.1 클래스 메서드를 위한 데코레이터
데코레이터는 클래스 메서드에도 사용할 수 있어. 중요한 것은 클래스 메서드에 올바르게 self
나 cls
인자를 전달해야 한다는 점이야.
클래스의 작동 원리는 아직 배우지 않았지만, 데코레이터가 이런 기능을 가지고 있다는 걸 알고 있으면 좋겠어.
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"메서드 {func.__name__} 호출")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("MyClass에서 안녕!")
obj = MyClass()
obj.say_hello()
설명
데코레이터 (log_method_call)
: 이 데코레이터는 메서드 func
를 받아 호출 전에 메시지를 출력하는 새로운 함수 wrapper
를 반환해.
데코레이터가 적용된 클래스 메서드 (say_hello)
: say_hello
메서드는 log_method_call
데코레이터로 감싸져 있어, 호출 시 추가적인 행동을 더해주지.
출력:
메서드 say_hello 호출
MyClass에서 안녕!
6.2 여러 개의 데코레이터
한 함수에 여러 개의 데코레이터를 겹쳐 사용할 수 있어. 데코레이터는 선언된 반대 순서대로 적용돼.
def decorator1(func):
def wrapper():
print("데코레이터 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("데코레이터 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("안녕!")
say_hello()
설명
데코레이터 (decorator1와 decorator2)
: 이 데코레이터는 func
호출 전에 자신의 메시지를 추가해.
데코레이터가 적용된 함수 (say_hello)
: say_hello
함수는 두 데코레이터로 감싸져 있어. 먼저 decorator2
가 적용되고, 그 다음 decorator1
이 적용돼.
출력:
# 데코레이터 1
# 데코레이터 2
안녕!
6.3 내장 데코레이터
Python은 static methods, class methods, properties 같은 표준 작업을 위한 몇 가지 내장 데코레이터를 제공해.
@staticmethod
데코레이터 @staticmethod
는 클래스 인스턴스 없이도 호출할 수 있는 정적 메서드를 만들 때 사용해.
class MyClass:
@staticmethod
def static_method():
print("이것은 정적 메서드야.")
MyClass.static_method()
@classmethod
데코레이터 @classmethod
는 인스턴스가 아니라 클래스를 첫 번째 인자로 받는 클래스 메서드를 만들 때 사용해.
class MyClass:
@classmethod
def class_method(cls):
print(f"이것은 {cls.__name__} 클래스 메서드야.")
MyClass.class_method()
@property
데코레이터 @property
는 속성의 getter, setter, deleter를 만들 때 사용해.
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # 출력: 10
obj.value = 20
print(obj.value) # 출력: 20
이러한 내장 데코레이터는 Python 인터프리터 자체에서 올바르게 동작해.
6.4 데코레이터 사용 예제
로깅
데코레이터는 함수와 메서드 호출을 로깅하는 데 사용할 수 있어.
def log_call(func):
def wrapper(*args, **kwargs):
print(f"함수 {func.__name__} 호출, 인자: {args}, 키워드 인자: {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
접근 제어
데코레이터는 함수와 메서드에 대한 접근을 제어하는 데 사용할 수 있어.
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("사용자가 인증되지 않았어.")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("사용자 프로필")
user = User(is_authenticated=True)
user.view_profile() # 성공적인 호출
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: 사용자가 인증되지 않았어.
캐싱
데코레이터는 함수 결과를 캐싱하는 데 사용할 수 있어.
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
GO TO FULL VERSION