- PEP-318 : 함수와 메서드의 기능을 쉽게 수정하기 위한 수단
- 데코레이터 이후에 나오는 것을 데코레이터의 첫 번째 파라미터로 하고 데코레이터의 결과 값을 반환하게 하는 문법적 설탕
- 데코레이터는 깔끔한 프로그래밍 interface를 정의하는 훌륭한 방법
- 좋은 데코레이터는 깔끔한 인터페이스를 제공하고 사용자가 내부 동작 원리를 자세히 몰라도 기대하는 바를 정확히 알 수 있게 해줘야 함
- 감싸고 있는 함수를 호출하기 전이나 후에 추가로 코드를 실행하는 기능
- 이 기능으로 입력 인수와 반환 값을 접근하거나 수정
- 시맨틱 강조, 디버깅, 함수 등록을 비롯해 여러 상황에 유용
- 표준 라이브러리
@staticmethod: 인스턴스를 생성하지 않아도 calss의 메서드를 바로 실행@classmethod: self 사용 가능@property- 변수를 변경 할 때 제한을 둘 때
- get, set 함수를 만들지 않고 접근 가능
- reference(link1)
- functools
@wraps: 원래의 함수를 디버깅, doctest 할 때 사용- reference(link1)
문법적 설탕(Syntax Sugar)
- 어떤 언어에서 동일한 기능이지만 간결성, 가독성을 높이기 위해 다른 표현으로 코딩할 수 있게 해주는 기능
def original(...):
...
original = modifier(original)
@modifier
def original(...):
...- 어떤 종류의 로직이라도 적용가능
- 유효성 검사
- 사전조건 검사
- 기능 전체 재정의
- 서명을 변경
- 원래 함수 결과 캐싱
- 클래스의 데코레이터는 남용할 경우
- 복잡하고 가독성을 떨어뜨림
- 클래스에서 정의한 속성과 메서드를 데코레이터 안에서 완전히 다른 용도로 변경 가능
- 코드 재사용, dry 원칙의 모든 이점 공유
- 여러 클래스가 특정 interface나 기준을 따르도록 강제할 수 있음
- 여러 클래스에 적용할 검사를 데코레이터에서 한 번만 하면 됨
- 작은 클래스를 생성하고, 데코레이터로 기능 보강
- 유지보수시 기존 로직을 훨씬 쉽게 변경
- 데코레이터는 스택 형태
- 제너레이터, 코루틴, 데코레이트된 객체도 데코레이터 가능
- 코루틴으로 사용되는 제너레이터
- 고차 함수(higher-order function) : 함수를 파라미터로 받아서 함수를 반환하는 함수
- 클래스를 사용하여 데코레이터 정의
__init__메서드에 파라미터 전달__call__매직 메서드에 데코레이터의 로직 구현
- 파라미터 변환
- 코드 추적
- 파라미터 유효성 검사
- 재시도 로직 구현
- 일부 반복 작업을 데코레이터로 이동하여 클래스 단순화
- 원본 함수의 일부 프로퍼티나 또는 속성을 유지하지 않아 원하지 않는 부작용 발생
help()함수가 새로운 함수의 이름을 출력- 개별 함수 확인이 어려움
- docstring이 덮어씌워짐 ⇒ doctest 모듈(mypy, pylint 등)로 확인 x
- 내장 모듈인 functools 의 wraps 사용
- 로그를 남기는 데코레이터
- 래핑된 함수라는 것을 알려줌
from functools import wraps
@wraps(func)- 데코레이터 함수가 되기 위해 필요한 하나의 조건은 가장 안쪽에 정의된 함수여야 한다는 것
- 그렇지 않으면 import에 문제가 발생할 수 있음
- 데코레이터 내에 @wraps 를 활용해 해결
- 부작용을 의도적으로 사용하여 실제 실행이 가능한 시점까지 기다리지 않는 경우
- ex) 모듈의 공용 레지스트리에 객체를 등록하는 경우
- 데코레이터를 만들 때 일반적으로 재사용을 고려하여 함수뿐 아니라 메서드에서도 동작하길 바람
*args,**kwargs서명을 사용하여 데코레이터를 정의하면 모든 경우에 사용할 수 있음
*args
- 여러개의 인자를 받을 때 사용
- tuple 형태로 받아옴
- 일반 변수보다 뒤에 위치해야 함
**kwargs
- {'key': 'value} 형태로 함수를 호출
- dict 형태로 함수 내부로 전달
- 그러나 다음 두 가지 이유로 원래 함수의 서명과 비슷하게 데코레이터를 정의하는 것이 좋을 때가 있다.
- 원래의 함수와 모양이 비슷하기 때문에 읽기 쉽다. (가독성)
- 파라미터를 받아서 뭔가를 하려면
*args,**kwargs사용하는 것이 불편
- 특정 기능을 한 번만 정의해서 사용(DRY)
- 컴포넌트가 충분히 재사용 가능한 추상화를 했다고 인정받기 위해서는 적어도 3가지 이상의 애플리케이션에서 시험해봐야 함
- 동시에 같은 레퍼런스에서 재사용 가능한 컴포넌트를 만드는 것은 일반 컴포넌트를 만드는 것보다 세 배 어렵다
- 처음부터 데고레이터를 만들지 않는다. 패턴이 생기고 데코레이터에 대한 추상화가 명확해지면 그 때 리팩토링 한다.
- 데코레이터가 적어도 3회 이상 필요한 경우에만 구현
- 데코레이터 코드를 최소한으로 유지
- 데코레이터에 하나 이상의 책임을 두면 안 된다. (SRP)
- 캡슐화와 관심사의 분리
- 좋은 데코레이터는 실제로 하는 일과 데코레이팅하는 일의 책임을 명확히 구분해야 함
- 어설프게 추상화 하면 안 됨
- 즉, 데코레이터의 클라이언트는 내부에서 어떻게 구현했는지 전혀 알 수 없는 블랙박스 모드로 동작해야 한다.
- 독립성
- 데코레이터가 하는 일은 독립적이어야 하며 데코레이팅되는 객체와 최대한 분리되어야 함
- 재사용성
- 데코레이터는 여러 유형에 적용 가능한 형태가 바람직
- 충분히 범용적이어야 함(저자는 최소 3개)