파이썬 데코레이터: 함수에 슈퍼 파워를 더합니다
안녕하세요, 파이썬 프로그래머를 꿈꾸는 여러분! 오늘은 파이썬 데코레이터의 흥미로운 세계에 빠지기 위해 준비했습니다. 데코레이터는 여러분의 함수에 슈퍼 파워를 더해줄 마법의 랩퍼라고 생각해보세요. 흥미롭지 않나요? 이 여정을 함께 떠나보세요!
데코레이터란 무엇인가요?
선물이 아름다운包装纸에 싸여 있다고 상상해보세요. 包装纸는 내부의 선물을 변경하지 않지만, 더 예뻐 보이죠? 이正是 데코레이터가 파이썬에서 여러분의 함수에 수행하는 일입니다. 함수를 감싸어 추가적인 기능을 제공하며, 원래의 함수를 변경하지 않습니다.
시작해볼 간단한 예제를 들어보겠습니다:
def my_decorator(func):
def wrapper():
print("함수가 호출되기 전에 무언가 일어나고 있습니다.")
func()
print("함수가 호출된 후에 무언가 일어나고 있습니다.")
return wrapper
@my_decorator
def say_hello():
print("안녕!")
say_hello()
이 코드를 실행하면 다음과 같은 출력이 나옵니다:
함수가 호출되기 전에 무언가 일어나고 있습니다.
안녕!
함수가 호출된 후에 무언가 일어나고 있습니다.
이를 분석해보겠습니다:
- 데코레이터 함수
my_decorator
를 정의하여 함수를 인자로 받습니다. -
my_decorator
내부에wrapper
함수를 정의하여 원래의 함수 호출 전후에 추가적인 동작을 수행합니다. -
@my_decorator
문법을 사용하여 데코레이터를say_hello
함수에 적용합니다. -
say_hello()
를 호출하면 실제로는 랩핑된 버전의 함수가 호출됩니다.
멋지지 않나요? 원래의 코드를 수정하지 않고 say_hello
함수에 추가적인 동작을 더해봤습니다!
데코레이터와 인자
하지만 기다려, 더 있습니다! 함수가 인자를 받는다면 어떻게 해야 하나요? 문제없습니다! 데코레이터를 수정하여 이를 처리할 수 있습니다:
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
여기서, *args
와 **kwargs
는 데코레이터가 위치 및 키워드 인자를 처리할 수 있게 합니다.
내장 데코레이터
파이썬은 매우 유용한 내장 데코레이터를 제공합니다. 이를 탐험해보겠습니다!
@classmethod
데코레이터
@classmethod
데코레이터는 클래스 자체에 대해 작동하는 메서드를 정의하는 데 사용됩니다, 클래스의 인스턴스가 아닙니다.
class Pizza:
def __init__(self, ingredients):
self.ingredients = ingredients
@classmethod
def margherita(cls):
return cls(['mozzarella', 'tomatoes'])
@classmethod
def prosciutto(cls):
return cls(['mozzarella', 'tomatoes', 'ham'])
print(Pizza.margherita().ingredients)
print(Pizza.prosciutto().ingredients)
이는 다음과 같은 출력을 내놓습니다:
['mozzarella', 'tomatoes']
['mozzarella', 'tomatoes', 'ham']
여기서, margherita
와 prosciutto
는 사전 정의된 재료로 새로운 Pizza 인스턴스를 생성하고 반환하는 클래스 메서드입니다.
@staticmethod
데코레이터
정적 메서드는 인스턴스나 클래스에 대해 작동하지 않는 메서드입니다. 그들은 단순히 클래스 내에 존재하는 정상적인 함수입니다.
class Math:
@staticmethod
def add(a, b):
return a + b
print(Math.add(5, 10))
이는 다음과 같은 출력을 내놓습니다:
15
@property
데코레이터
@property
데코레이터는 속성처럼 접근할 수 있는 메서드를 정의할 수 있게 합니다.
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@property
def area(self):
return 3.14 * self._radius ** 2
c = Circle(5)
print(c.radius)
print(c.area)
이는 다음과 같은 출력을 내놓습니다:
5
78.5
여기서, radius
와 area
를 속성처럼 접근할 수 있지만, 실제로는 메서드입니다.
@functools.wraps
데코레이터
이 데코레이터는 데코레이터를 생성할 때 원래의 함수의 메타데이터를 보존하는 데 사용됩니다.
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""이것은 wrapper 함수입니다"""
return func(*args, **kwargs)
return wrapper
@my_decorator
def my_function():
"""이것은 내 함수입니다"""
pass
print(my_function.__name__)
print(my_function.__doc__)
이는 다음과 같은 출력을 내놓습니다:
my_function
이것은 내 함수입니다
@wraps
없이는 함수 이름과 독스트링은 wrapper 함수의 것이 됩니다.
결론
데코레이터는 파이썬에서 함수와 메서드를 수정하거나 개선할 수 있는 강력한 기능입니다. 이는 로깅, 접근 제어 등을 추가하는 프레임워크와 라이브러리에서 널리 사용됩니다.
기억해두세요, 데코레이터를 마스터하기 위한 키는 연습입니다. 여러분 자신의 데코레이터를 만들어 다양한 함수에 적용해보세요. 곧, 여러분의 함수에 슈퍼 파워를 더하는 프로길이 될 것입니다!
다음은 우리가 다룬 데코레이터를 요약한 표입니다:
데코레이터 | 목적 |
---|---|
@classmethod |
클래스 자신에 대해 작동하는 메서드를 정의 |
@staticmethod |
인스턴스나 클래스에 대해 작동하지 않는 메서드를 정의 |
@property |
속성처럼 접근할 수 있는 메서드를 정의 |
@functools.wraps |
데코레이터를 생성할 때 원래의 함수의 메타데이터를 보존 |
코드를 즐겁게, 여러분의 함수가 항상 아름다워지길 바랍니다!
Credits: Image by storyset