Python 장식 기 사용 설명
로그 삽입,성능 테스트,사무 처리,캐 시,권한 검사 등 장면 에 자주 사 용 됩 니 다.장식 기 는 이런 문 제 를 해결 하 는 가장 좋 은 디자인 이다.장식 기 가 있 으 면 우 리 는 함수 기능 자체 와 무관 한 유사 코드 를 대량으로 추출 하여 계속 재 활용 할 수 있다.
먼저 간단 한 예 를 보 자.
def now():
print('2017_7_29')
함수 의 실행 로 그 를 기록 하고 싶 어서 코드 에 로그 코드 를 추가 합 니 다.
def now():
print('2017_7_29')
logging.warn("running")
비슷 한 여러 가지 수요 가 있다 고 가정 하면 어떻게 합 니까?logging 을 하나 더 써 서 now 함수 에?이렇게 하면 대량의 유사 한 코드 를 만 들 수 있 습 니 다.중복 코드 를 줄 이기 위해 서 우 리 는 이렇게 할 수 있 습 니 다.로 그 를 전문 적 으로 처리 하고 로 그 를 처리 한 후에 진정한 업무 코드 를 실행 할 수 있 습 니 다.
def use_logging(func):
logging.warn("%s is running" % func.__name__)
func()
def now():
print('2017_7_29')
use_logging(now)
실현 은 논리 적 으로 어렵 지 않 지만,이렇게 되면 우 리 는 매번 하나의 함 수 를 매개 변수 로 로그 함수 에 전달 해 야 한다.그리고 이런 방식 은 기 존의 코드 논리 구 조 를 파괴 했다.이전에 업무 논 리 를 실 행 했 을 때 now()를 실 행 했 지만 지금 은 use 로 바 꿀 수 밖 에 없다.logging(now)。그렇다면 더 좋 은 방법 은 없 을 까?물론 있 습 니 다.정 답 은 장식 기 입 니 다.먼저 함수 도 하나의 대상 이 고 함수 대상 이 변수 에 할당 되 기 때문에 변 수 를 통 해 이 함 수 를 호출 할 수 있다 는 것 을 알 아야 한다.예 를 들 면:
def now():
print('2017_7_28')
f=now
f()
# __name__ ,
print('now.__name__:',now.__name__)
print('f.__name__:',f.__name__)
단순 장식 기본질 적 으로 decorator 는 함수 로 돌아 가 는 고급 함수 입 니 다.따라서 로 그 를 인쇄 할 수 있 는 decorator 를 정의 하려 면 다음 과 같이 정의 할 수 있 습 니 다.
def log(func):
def wrapper(*args,**kw):
print('call %s():'%func.__name__)
return func(*args,**kw)
return wrapper
\#log()는 decorator 로 함수 하 나 를 되 돌려 주기 때문에 원래 의 now()함수 가 존재 합 니 다.\#현재 같은 이름 의 now 변 수 는 새로운 함 수 를 가리 키 고 있 습 니 다.그래서 now()를 호출 하면 로그()함수 에서 돌아 오 는 wrapper()함 수 를 실행 합 니 다.
\#wrapper()함수 의 매개 변 수 는(*args,**kw)로 정의 되 므 로 wrapper()함수 가 임의의 매개 변 수 를 호출 할 수 있 습 니 다.
\#wrapper()함수 에서 로 그 를 먼저 인쇄 한 다음 원본 함 수 를 호출 합 니 다.
위의 log 는 decorator 이기 때문에 함수 하 나 를 매개 변수 로 받 아들 이 고 함수 하 나 를 되 돌려 줍 니 다.현재 실행:
now = log(now)
now()
출력 결과:call now():
2017_7_28
함수 log 는 장식 기 입 니 다.실제 업무 방법 을 수행 하 는 func 를 함수 에 감 싸 서 now 가 log 로 장식 한 것 처럼 보 입 니 다.이 예 에서 함수 가 들 어 갈 때 횡단면(Aspect)이 라 고 불 리 며,이러한 프로 그래 밍 방식 은 절단면 을 위 한 프로 그래 밍(Aspect-Oriented Programming)이 라 고 불 린 다.
문법 사탕 사용 하기:
@log
def now():
print('2017_7_28')
@기 호 는 장식 기의 문법 사탕 입 니 다.함 수 를 정의 할 때 사용 하고 다시 할당 하지 않도록 합 니 다.이렇게 하면 우 리 는 now=log(now)라 는 말 을 줄 일 수 있 습 니 다.now()를 직접 호출 하면 원 하 는 결 과 를 얻 을 수 있 습 니 다.만약 우리 가 다른 유사 한 함수 가 있다 면,우 리 는 함 수 를 반복 적 으로 수정 하거나 새로운 패 키 지 를 추가 하지 않 고 장식 기 를 계속 호출 하여 함 수 를 수식 할 수 있 습 니 다.이렇게 해서 우 리 는 프로그램의 중복 이용 성 을 높이 고 프로그램의 가 독성 을 증가 시 켰 다.
장식 기 가 Python 에서 이렇게 편리 하 게 사용 하 는 것 은 Python 의 함수 가 일반적인 대상 처럼 매개 변수 로 다른 함수 에 전달 할 수 있 기 때 문 입 니 다.다른 변수 에 값 을 부여 할 수 있 고 반환 값 으로 다른 함수 에 정의 할 수 있 습 니 다.
인자 가 있 는 장식 기:
decorator 자체 에 인 자 를 입력 해 야 한다 면 decorator 로 돌아 가 는 고급 함 수 를 만들어 야 합 니 다.복잡 하 게 쓸 수 있 습 니 다.예 를 들 어 로그 의 텍스트 를 사용자 정의 하려 면:
def log(text):
def decorator(func):
def wrapper(*args,**kw):
print('%s %s()'%(text,func.__name__))
return func(*args,**kw)
return wrapper
return decorator
이 3 층 에 포 함 된 decorator 의 용법 은 다음 과 같다.
@log('goal')
def now():
print('2017-7-28')
now()
등가now = log('goal')(now)
\#먼저 log('execute')를 실행 하고 decorator 함 수 를 되 돌려 주 며 되 돌아 오 는 함 수 를 호출 합 니 다.매개 변 수 는 now 함수 이 고 되 돌아 오 는 값 은 최종 적 으로 wrapper 함수 입 니 다.now()
우리 가 함수 도 대상 이 라 고 말 했 기 때문에,그것 은 가 있다.name__등 속성,하지만 decorator 장식 을 거 친 함수,그들의 를 보 세 요.name__이미 원래 의'now'에서'wrapper'로 바 뀌 었 다.
print(now.__name__)
# wrapper
돌아 오 는 그 wrapper()함수 이름 이'wrapper'이기 때문에 원시 함수 의 를name__wrapper()함수 에 속성 을 복사 하지 않 으 면 함수 서명 에 의존 하 는 코드 가 실 행 될 수 있 습 니 다.wrapper 를 만 들 필요 가 없습니다.name__ = func.__name__이러한 코드 는 Python 에 내 장 된 funtools.wraps 가 바로 이 일 을 하 는 것 입 니 다.따라서 완전한 decorator 의 작성 방법 은 다음 과 같 습 니 다.
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
클래스 장식 기:다시 한 번 류 장식 기 를 살 펴 보면 함수 장식 기 에 비해 류 장식 기 는 유연성 이 크 고 내부 집적,포장 성 등 장점 을 가진다.클래스 장식 기 를 사용 하면 클래스 내부 의 에 의존 할 수 있 습 니 다.call__방법 은@형식 으로 장식 기 를 함수 에 추가 할 때 이 방법 을 사용 합 니 다.
import time
class Foo(object):
def __init__(self, func):
self._func = func
def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')
@Foo
def now():
print (time.strftime('%Y-%m-%d',time.localtime(time.time())))
now()
요약:요약 하면 장식 기의 역할 은 이미 존재 하 는 대상 에 게 추가 적 인 기능 을 추가 하 는 것 이다.
동시에 대상(OOP)을 대상 으로 하 는 디자인 모델 에서 decorator 는 장식 모델 이 라 고 불 린 다.OOP 의 장식 모델 은 계승 과 조합 을 통 해 이 루어 져 야 하 며,Python 은 OOP 의 decorator 를 지원 할 수 있 는 것 을 제외 하고 문법 적 차원 에서 decorator 를 직접 지원 합 니 다.Python 의 decorator 는 함수 로 이 루어 질 수도 있 고 클래스 로 이 루어 질 수도 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.