데코레이터는 파이썬에서 함수 또는 메서드를 수정하지 않고도 추가 기능을 부여할 수 있는 강력한 기능입니다. 주로 코드의 재사용성, 유지보수성, 가독성을 높이는 데 사용됩니다. 데코레이터는 기존 함수에 기능을 "랩핑"하여 호출 전후로 특정 작업을 수행하도록 합니다.
1. 데코레이터의 기본 구조
데코레이터는 다른 함수를 인자로 받아 새로운 함수를 반환하는 함수로 정의됩니다.
def my_decorator(func):
def wrapper():
print("함수 실행 전")
func()
print("함수 실행 후")
return wrapper
설명: my_decorator 함수는 func를 받아 wrapper라는 새 함수를 반환합니다. wrapper는 func를 호출 전후에 추가 기능을 실행합니다.
2. 데코레이터 적용 방법
데코레이터는 함수 정의 위에 @데코레이터이름으로 적용합니다.
@my_decorator
def say_hello():
print("Hello!")
say_hello()
결과:
함수 실행 전
Hello!
함수 실행 후
설명: say_hello() 함수를 호출하면 @my_decorator 데코레이터가 적용되어 wrapper 함수가 실행됩니다. 따라서 say_hello() 함수는 "함수 실행 전", "Hello!", "함수 실행 후" 순으로 출력됩니다.
3. 인자를 받는 함수에 데코레이터 적용
인자를 받는 함수에 데코레이터를 적용하려면 *args와 **kwargs를 사용하여 모든 인자를 전달받도록 합니다.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("함수 실행 전")
result = func(*args, **kwargs)
print("함수 실행 후")
return result
return wrapper
@my_decorator
def add(a, b):
return a + b
print(add(3, 5))
결과:
함수 실행 전
함수 실행 후
8
설명: add(3, 5) 호출 시, @my_decorator가 add 함수를 래핑하여 "함수 실행 전", "함수 실행 후"를 출력하고, 결과로 8을 반환합니다.
4. 여러 데코레이터 중첩 적용
여러 데코레이터를 중첩해서 적용할 수 있습니다. 데코레이터는 위에서 아래 순서로 적용됩니다.
def bold(func):
def wrapper(*args, **kwargs):
return "<b>" + func(*args, **kwargs) + "</b>"
return wrapper
def italic(func):
def wrapper(*args, **kwargs):
return "<i>" + func(*args, **kwargs) + "</i>"
return wrapper
@bold
@italic
def text():
return "Hello, World!"
print(text())
결과:
<b><i>Hello, World!</i></b>
설명: @italic가 먼저 적용되어 <i>...</i>로 감싸지고, 그 다음 @bold가 적용되어 최종 출력이 <b><i>Hello, World!</i></b>로 반환됩니다.
5. 함수 실행 시간 측정 데코레이터 예제
데코레이터는 함수의 실행 시간을 측정하는 데 유용하게 사용될 수 있습니다.
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"실행 시간: {end_time - start_time:.4f}초")
return result
return wrapper
@timer
def slow_function():
time.sleep(2)
print("작업 완료")
slow_function()
결과:
작업 완료
실행 시간: 2.0003초
설명: @timer 데코레이터는 함수 실행 전후의 시간을 측정하고, slow_function()의 실행 시간을 출력합니다.
6. 접근 제어 데코레이터 (예: 로그인 필요)
특정 기능을 수행하기 전 사용자 인증이 필요할 때 데코레이터를 활용하여 접근 제어를 할 수 있습니다.
def requires_login(func):
def wrapper(user, *args, **kwargs):
if not user.get("is_logged_in"):
print("로그인이 필요합니다.")
return
return func(user, *args, **kwargs)
return wrapper
@requires_login
def view_profile(user):
print(f"{user['name']}님의 프로필을 보여줍니다.")
# 예제 사용자
user = {"name": "Alice", "is_logged_in": False}
view_profile(user) # 결과: 로그인이 필요합니다.
user["is_logged_in"] = True
view_profile(user) # 결과: Alice님의 프로필을 보여줍니다.
설명: @requires_login 데코레이터는 user 딕셔너리의 is_logged_in 값이 True인지 확인하여, 로그인 여부에 따라 함수 실행을 제어합니다.
7. 클래스 메서드에 데코레이터 적용
데코레이터는 클래스 메서드에도 사용할 수 있습니다. 클래스 메서드나 정적 메서드에 데코레이터를 적용하려면 @classmethod나 @staticmethod와 함께 사용할 수 있습니다.
def log_method_call(func):
def wrapper(*args, **kwargs):
print(f"{func.__name__} 메서드가 호출되었습니다.")
return func(*args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def instance_method(self):
print("인스턴스 메서드 실행")
@classmethod
@log_method_call
def class_method(cls):
print("클래스 메서드 실행")
my_instance = MyClass()
my_instance.instance_method()
MyClass.class_method()
결과:
instance_method 메서드가 호출되었습니다.
인스턴스 메서드 실행
class_method 메서드가 호출되었습니다.
클래스 메서드 실행
설명: @log_method_call 데코레이터가 instance_method와 class_method 호출 시마다 실행되어, 메서드 호출을 로깅합니다.
8. 인자를 받는 데코레이터
데코레이터에 인자를 전달하려면, 데코레이터를 한 번 더 감싸는 함수를 사용합니다.
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet():
print("Hello!")
greet()
결과:
Hello!
Hello!
Hello!
설명: @repeat(3) 데코레이터는 greet() 함수를 세 번 반복해서 호출하도록 만듭니다.
데코레이터는 코드의 재사용성과 유지보수성을 높여주며, 프로그램에 유연한 기능을 추가하는 데 매우 유용합니다.
'파이썬 Python' 카테고리의 다른 글
파이썬(Python) JSON 처리 (0) | 2024.11.26 |
---|---|
파이썬 Python 날짜와 시간 다루기 (0) | 2024.11.26 |
파이썬 Python 파일 경로 다루기 (0) | 2024.11.23 |
파이썬 Python 제너레이터와 이터레이터 사용하기 (0) | 2024.11.23 |
파이썬 Python 문자열 다루기 (0) | 2024.11.21 |
파이썬 Python 패키지 관리자 (pip) (0) | 2024.11.18 |
파이썬 Python 모듈과 라이브러리 사용하는 방법 (0) | 2024.11.18 |
파이썬 Python 파일 입출력 (File I/O) 사용하기 (1) | 2024.11.13 |