데코레이터는 파이썬 프로그래머들 사이에서 매력적인 도구로 알려져 있습니다. 간결하면서도 효율적인 코드를 작성하는 데 큰 도움을 주기 때문이죠. 이 글에서는 데코레이터의 기본 원리부터 실용적인 활용 방법까지 깊게 탐색해보려 합니다.
데코레이터란 무엇인가?
함수와 클래스에 대한 간단한 복습
파이썬에서 함수는 def 키워드로 정의되며, 입력값을 받아 처리 후 결괏값을 반환하는 역할을 합니다. 클래스는 class 키워드를 사용하여 정의하며, 객체 지향 프로그래밍의 핵심 요소입니다. 클래스 안에는 메서드와 속성이 포함될 수 있습니다.
def function_example(a, b):
return a + b
class ClassExample:
def __init__(self, data):
self.data = data
def method_example(self):
return self.data * 2
데코레이터로 파이썬 함수 강화하기
데코레이터는 파이썬에서의 강력한 도구로, 기존 함수를 수정하지 않고도 그 함수의 출력을 수정할 수 있게 해 줍니다
- 기존 함수를 수정하지 않고 새로운 기능을 추가할 수 있습니다.
- 코드를 보다 간결하고 효율적으로 작성할 수 있습니다.
- 코드의 재사용성을 높일 수 있습니다.
def decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@decorator
def say_hello():
print("Hello!")
say_hello()
# Output:
# Before function call
# Hello!
# After function call
활용 예제들
1. 인자를 로깅하는 데코레이터
많은 경우에, 함수가 어떤 인자와 함께 호출되었는지 로깅하고 싶을 수 있습니다.
아래의 데코레이터는 함수 호출 시 인자를 로깅합니다.
def log_args_decorator(func):
def wrapper(*args, **kwargs):
print(f"Function {func.__name__} called with arguments {args} and keyword arguments {kwargs}.")
return func(*args, **kwargs)
return wrapper
@log_args_decorator
def add(a, b):
return a + b
add(5, 3)
# Output: Function add called with arguments (5, 3) and keyword arguments {}.
2. 함수 실행 시간 측정 데코레이터
함수의 실행 시간을 측정하여, 성능 최적화가 필요한 부분을 파악할 수 있습니다.
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.2f} seconds to run.")
return result
return wrapper
@timing_decorator
def simulate_long_task():
time.sleep(2)
simulate_long_task()
# Output: Function simulate_long_task took 2.00 seconds to run.
3. 권한 확인 데코레이터
API 또는 웹 애플리케이션에서 특정 역할을 가진 사용자만 함수나 메서드를 실행할 수 있도록 권한을 검사하는 데코레이터입니다.
def admin_required(func):
def wrapper(user, *args, **kwargs):
if user.get('role') != 'admin':
raise PermissionError("Only admin users can execute this function.")
return func(user, *args, **kwargs)
return wrapper
@admin_required
def view_admin_dashboard(user):
return "Welcome to the admin dashboard!"
user = {'username': 'john', 'role': 'admin'}
print(view_admin_dashboard(user)) # Output: Welcome to the admin dashboard!
user = {'username': 'jane', 'role': 'member'}
# Raises PermissionError: Only admin users can execute this function.
사용할 때 주의점
데코레이터를 사용할 때 주의해야 할 몇 가지 중요한 사항이 있습니다. 이러한 주의점을 이해하고 올바른 방법으로 데코레이터를 구현하면 예기치 않은 버그나 이슈를 피할 수 있습니다.
1. 원래 함수의 메타데이터 유지
데코레이터를 사용하면 함수의 원래 메타데이터 (예: 이름, 문서 문자열)가 손실될 수 있습니다. 이를 방지하기 위해 functools.wraps를 사용하여 원래 함수의 메타데이터를 데코레이터 함수에 복사할 수 있습니다.
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 데코레이터의 기능 구현
return func(*args, **kwargs)
return wrapper
@my_decorator
def my_function():
"""이것은 예제 함수입니다."""
pass
print(my_function.__name__) # 'my_function'
print(my_function.__doc__) # '이것은 예제 함수입니다.'
functools.wraps를 사용하지 않으면, my_function.__name__은 'wrapper'로 출력되었을 것입니다.
2. 인자를 받는 데코레이터 구현
데코레이터가 인자를 받을 수 있도록 구현할 때는 추가적인 함수 레벨이 필요합니다. 이를 주의 깊게 처리하지 않으면 데코레이터의 동작에 문제가 발생할 수 있습니다.
def repeat(num_times):
def decorator_repeat(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"안녕하세요, {name}!")
greet("홍길동") # "안녕하세요, 홍길동!"이 세 번 출력됩니다.
3. 반환 값 다루기
데코레이터 내에서 원래 함수의 반환 값을 적절히 처리하지 않으면, 데코레이터를 적용한 함수의 반환 값이 예상과 다를 수 있습니다. 따라서 데코레이터를 구현할 때는 원래 함수의 반환 값을 적절히 처리하도록 주의해야 합니다.
def double_return(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result * 2
return wrapper
@double_return
def add(a, b):
return a + b
print(add(2, 3)) # 예상 결과: 5, 실제 결과: 10
add 함수의 반환 값이 두 배로 증가하는 것을 확인할 수 있습니다.
이러한 주의점을 기억하며 데코레이터를 구현하면, 데코레이터의 예상치 않은 부작용을 최소화할 수 있습니다.
데코레이터는 파이썬 프로그래머들 사이에서 매력적인 도구로 알려져 있습니다. 간결하면서도 효율적인 코드를 작성하는 데 큰 도움을 주기 때문이죠. 이 글에서는 데코레이터의 기본데코레이터는 파이썬에서 강력한 코드 최적화 도구로써, 올바르게 활용한다면 코드의 품질을 크게 향상할 수 있습니다. 그렇기에 데코레이터의 원리와 활용 방법을 꼭 숙지하시길 바랍니다. 이 글을 통해 데코레이터의 기본적인 이해와 활용 방법에 대한 아이디어를 얻으셨기를 바라며, 다음 글에서 또 다른 유익한 파이썬 팁을 공유하겠습니다. 감사합니다!
'프로그래밍 언어(Programming Languages) > 파이썬(Python)' 카테고리의 다른 글
[Python] isinstance() 함수 활용하기! 📘✨ (30) | 2023.11.07 |
---|---|
[Python] @property 데코레이터로 캡슐화 구현하기 🛡️🐍 (38) | 2023.11.06 |
[Python] 파이썬 함수의 세계: 각종 함수 유형 마스터하기 - 2탄 (41) | 2023.10.17 |
[Python] 파이썬 함수의 세계: 각종 함수 유형 마스터하기 - 1탄 (52) | 2023.10.16 |
[Python] @dataclass로 서점 데이터베이스 만들기 (18) | 2023.10.13 |