데코레이터
함수나 클래스의 동작을 수정하거나 확장하는 기능을 제공하는 도구
- 함수나 클래스의 정의 위에 '@' 기호를 사용하여 적용한다.
- 데코레이터의 기능 및 장점은 다음과 같다.
- 함수 및 메서드 수정: 데코레이터를 사용하여 기존 함수나 메서드의 동작을 수정하거나 확장할 수 있다. 이를 통해 코드 중복을 줄이고 재사용성을 높일 수 있다.
- 함수 및 메서드의 기능 추가: 데코레이터를 사용하여 함수나 메서드에 추가적인 기능을 쉽게 적용할 수 있다.
- 코드 가독성 향상: 데코레이터를 사용하면 코드를 더 읽기 쉽고 이해하기 쉽게 만들 수 있다. 함수나 메서드의 주요 기능과 추가 기능이 분리되어 있어 코드의 구조가 명확해진다.
- 재사용성과 모듈화: 데코레이터를 작성하면 동일한 기능을 여러 함수나 메서드에 쉽게 적용할 수 있다. 이렇게 하면 코드를 모듈화하고 재사용성을 높일 수 있다.
- 함수 패턴 유지: 데코레이터를 사용하면 원래 함수나 메서드의 시그니처(Signature)를 변경하지 않고도 기능을 추가하거나 수정할 수 있다. (시그니처에는 함수나 메서드의 이름, 매개변수 목록, 반환값 등이 포함된다.)
데코레이터 함수
# 데코레이터 함수 정의
def my_decorator(func):
def wrapper():
print("데코레이터 전처리")
func()
print("데코레이터 후처리\n")
return wrapper
# 데코레이터를 사용하여 함수 수정
@my_decorator
def say_hello():
print("hello!")
@my_decorator
def say_world():
print("world!")
# 함수 호출
say_hello()
say_world()
데코레이터 전처리
hello!
데코레이터 후처리
데코레이터 전처리
world!
데코레이터 후처리
- 위 예제에서는 my_decorator 데코레이터 함수가 say_hello와 say_world 함수를 감싸고 전처리와 후처리 단계를 추가한다.
- 결과와 같이 데코레이터를 사용하면 기존 함수의 동작을 유지하면서 기능을 추가하거나 수정하는 것이 가능하다.
클래스에서 데코레이터 사용하기
정적메서드 (@staticmethod)
- 정적 메서드는 클래스와 인스턴스와 상관없이 호출될 수 있으며, 클래스나 인스턴스 변수에 접근할 수 없다.
- 클래스에 무관한 독립적인 유틸리티 함수를 만들 때 사용된다.
- 입력 값에만 의존하고, 외부상태에 영향을 받거나 외부상태를 변경하지 않는 순수 함수(Pure Function)을 생성할 때 사용
- 순수 함수는 동일한 입력에 대해 항상 동일한 출력을 갖는다.
- 정적 메서드는 단순히 클래스 내부에 존재하는 함수이다.
class MathUtils:
@staticmethod
def add(x, y):
return x + y
@staticmethod
def subtract(x, y):
return x - y
# 정적 메서드 호출
result1 = MathUtils.add(5, 3) # 5 + 3 = 8
result2 = MathUtils.subtract(10, 4) # 10 - 4 = 6
print(result1, result2)
8 6
클래스메서드 (@classmethod)
- 클래스 메서드는 클래스 레벨에서 호출되며, 첫 번째 매개변수로 클래스 자체를 받는다. 이를 통해 클래스 변수에 접근할 수 있다.
- 인스턴스를 생성한 후에도 클래스 메서드를 호출할 수 있다.
class MyClass:
class_variable = "클래스 변수"
def __init__(self, instance_variable):
self.instance_variable = instance_variable
@classmethod
def class_method(cls):
print(f"클래스 메서드 호출: {cls.class_variable}")
# 클래스 메서드 호출
MyClass.class_method() # 출력: 클래스 메서드 호출: 클래스 변수
# 인스턴스 생성 후 클래스 메서드 호출
obj = MyClass("인스턴스 변수")
obj.class_method() # 출력: 클래스 메서드 호출: 클래스 변수
클래스 메서드 호출: 클래스 변수
클래스 메서드 호출: 클래스 변수
- 클래스 메서드의 첫 번째 매개변수 cls는 현재 클래스인 MyClass 자체를 나타낸다. (관례적으로 클래스 메서드의 첫 번째 매개변수는 cls라는 약자를 사용)
- 따라서 클래스 변수인 class_variable에 접근할 수 있으며, 클래스 메서드 내에서 클래스 변수와 메서드 같은 클래스 수준의 정보를 조작하거나 사용하는 데 주로 사용된다.
Getter/Setter
- Getter와 Setter는 클래스의 멤버 변수(속성)에 접근하고 조작하는 메서드를 정의하는 데 사용된다.
- Getter와 Setter를 사용하면 클래스의 속성에 대한 접근과 조작을 더욱 제어할 수 있다. -> 데이터 캡슐화 및 정보 은닉
Getter
- 클래스의 속성 값을 반환하는 메서드
- 다른 코드에서 클래스의 속성 값을 읽을 때 사용된다.
- 보통 'get_' 또는 속성의 이름과 유사한 이름으로 메서드를 정의한다.
class Person:
def __init__(self, name):
self._name = name # 속성 앞에 밑줄은 가상적으로 '비공개' 속성임을 표시
def get_name(self): # getter
return self._name
person = Person("Daniel")
print(person.get_name())
Daniel
Setter
- 클래스의 속성 값을 설정 또는 변경하는 메서드
- 다른 코드에서 클래스의 속성 값을 수정할 때 사용된다.
- 보통 'set_' 또는 속성의 이름과 유사한 이름으로 메서드를 정의한다.
- Setter 메서드 내에서 입력 값을 검증하거나 다양한 조작을 수행할 수 있다.
class Person:
def __init__(self, name):
self._name = name # 속성 앞에 밑줄은 가상적으로 '비공개' 속성임을 표시
def get_name(self): # getter
return self._name
def set_name(self, new_name): # setter
if not isinstance(new_name, str):
raise ValueError("이름은 반드시 str 타입이어야 합니다.")
self._name = new_name
person = Person("Daniel")
person.set_name("Paul")
print(person.get_name())
Paul
속성 데코레이터 (@property)
- 속성 데코레이터는 파이썬 클래스 내부의 메서드를 속성처럼 접근할 수 있게 해주는 기능을 제공한다.
- 이를 사용하여 클래스의 메서드를 속성처럼 읽을 수 있으며, 필요한 경우 해당 속성에 대한 getter 메서드는 이용하여 계산된 값을 반환할 수 있다.
속성 데코레이터 (getter/setter)
- '@property' 데코레이터를 사용하여 Getter를 구현하고, '@속성이름.setter' 데코레이터를 사용하여 Setter를 구현할 수 있다.
- 이를 통해 메서드 형태로 Getter와 Setter를 정의하지 않고도 속성을 제어할 수 있다.
예제
class Person:
def __init__(self, name):
self._name = name # 속성 앞에 밑줄은 가상적으로 '비공개' 속성임을 표시
@property
def name(self):
return self._name
@name.setter
def name(self, new_name):
if not isinstance(new_name, str):
raise ValueError("이름은 반드시 str 타입이어야 합니다.")
self._name = new_name
person = Person("Daniel")
# Getter 호출
print(person.name)
# Setter 호출
person.name = "Paul"
print(person.name)
Daniel
Paul
- '@property' 데코레이터는 'name' 메서드를 Getter로, '@name.setter'는 'name' 메서드를 Setter로 정의한다.
- 이를 통해서 'person.name'을 속성처럼 읽고 쓸 수 있다.