데코레이터실행순서
def make_bold(fn):
return lambda : "<b>" + fn() + "</b>"
def make_italic(fn):
return lambda : "<i>" + fn() + "</i>"
@make_bold
@make_italic
def hello():
return "hello world"
helloHTML = hello()
출력:"<b><i>hello world</i></b>"
저는 장식가에 대해 대략적으로 이해하고 있으며 대부분의 예에서 장식가 중 하나와 어떻게 작동하는지 이해합니다.
이 예제에는 두 가지가 있습니다.출력으로 볼 때, 다음과 같습니다.@make_italic먼저 실행한 다음@make_bold.
장식된 기능의 경우 먼저 기능을 실행한 후 다른 장식가를 위해 맨 위로 이동한다는 의미입니까?맘에 들다@make_italic그 다음에@make_bold반대로
그래서 이것은 대부분의 프로그래밍 언어에서 하향식 접근의 표준과 다르다는 것을 의미합니까?이 장식가의 경우에만?아니면 제가 틀렸나요?
장식가들은 장식하고 있는 기능을 포장합니다.그렇게make_bold의 결과를 장식했습니다.make_italic장식가, 그것은 장식했습니다.hello기능.
그@decorator구문은 실제로 구문 설탕입니다; 다음과 같습니다.
@decorator
def decorated_function():
# ...
실제로는 다음과 같이 실행됩니다.
def decorated_function():
# ...
decorated_function = decorator(decorated_function)
원본 교체decorated_function무엇이든 반대하는decorator()반환된
적층 장식기는 이 과정을 바깥쪽으로 반복합니다.
그래서 당신의 경우:
@make_bold
@make_italic
def hello():
return "hello world"
다음으로 확장할 수 있습니다.
def hello():
return "hello world"
hello = make_bold(make_italic(hello))
전화할 때hello()이제, 당신은 반환된 물체를 부르고 있습니다.make_bold(),정말로. make_bold()대답했습니다.lambda함수를 호출합니다.make_bold포장됨, 이것은 반환 값입니다.make_italic()원본을 호출하는 람다이기도 합니다.hello()수신되는 모든 통화를 확장합니다.
hello() = lambda : "<b>" + fn() + "</b>" # where fn() ->
lambda : "<i>" + fn() + "</i>" # where fn() ->
return "hello world"
따라서 출력은 다음과 같습니다.
"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"
나는 이 질문에 대한 답이 간단해 보이지만 그렇지 않다고 생각합니다.우리가 데코레이터의 실행 순서에 대해 이야기할 때, 나는 파이썬 인터프리터가 장식된 메소드 정의 자체를 평가할 때와 장식된 메소드가 호출/실행될 때, 장식된 메소드 자체가 실행 중에 다른 순간에 평가된다는 것을 기억해야 한다고 생각합니다.제 실험에서 알 수 있듯이 장식가들의 순서는 이 두 단계 사이에서 다릅니다.
또한 함수를 장식할 때 장식된 메서드 앞에 실행되는 코드와 그 이후에 실행되는 코드가 있을 수 있다는 것을 기억하십시오.이것은 장식가들을 둥지를 틀 때 상황을 훨씬 더 복잡하게 만듭니다.
그래서, 몇 마디로:
- 통역사가 장식된 방법 정의를 평가할 때 장식자는 아래에서 평가됩니다 --> 위에서
- 통역사가 장식 방법을 부를 때, 장식자들은 위에서 --> 아래에서 부릅니다.
다음 코드 예제를 생각해 보십시오.
print("========== Definition ==========")
def decorator(extra):
print(" in decorator factory for %s " % extra)
extra = " %s" % extra
def inner(func):
print(" defining decorator %s " % extra)
def wrapper(*args, **kwargs):
print("before %s -- %s" % (func.__name__, extra))
func(*args, **kwargs)
print("after %s -- %s" % (func.__name__, extra))
return wrapper
return inner
@decorator('first')
@decorator('middle')
@decorator('last')
def hello():
print(' Hello ')
print("\n========== Execution ==========")
hello()
이 코드의 출력은 다음과 같습니다.
========== Definition ==========
in decorator factory for first
in decorator factory for middle
in decorator factory for last
defining decorator last
defining decorator middle
defining decorator first
========== Execution ==========
before wrapper -- first
before wrapper -- middle
before hello -- last
Hello
after hello -- last
after wrapper -- middle
after wrapper -- first
이 출력에서 볼 수 있듯이 순서가 다릅니다(앞에서 설명한 것처럼).정의 중에는 장식가가 아래에서 위로 평가되는 반면 실행 중에는(일반적으로 가장 중요한 부분) 위에서 아래로 평가됩니다.
질문에서 제안된 예로 돌아가서 다음은 (람다를 사용하지 않은) 샘플 코드입니다.
print("========== Definition ==========")
def make_bold(fn):
print("make_bold decorator")
def wrapper():
print("bold")
return "<b>" + fn() + "</b>"
return wrapper
def make_italic(fn):
print("make_italic decorator")
def wrapper():
print("italic")
return "<i>" + fn() + "</i>"
return wrapper
@make_bold
@make_italic
def hello():
return "hello world"
print("\n========== Execution ==========")
print(hello())
이 경우 출력은 다음과 같습니다.
========== Definition ==========
make_italic decorator
make_bold decorator
========== Execution ==========
bold
italic
<b><i>hello world</i></b>
새로 실행 순서는 위에서 아래로 진행됩니다.원본 코드에도 동일하게 적용할 수 있습니다(여기가 어디인지 인쇄하기 위해 약간 수정됨).
print("========== Definition ==========")
def make_bold(fn):
print("make_bold")
return lambda: print("exec_bold") or "<b>" + fn() + "</b>"
def make_italic(fn):
print("make_italic")
return lambda: print("exec_italic") or "<i>" + fn() + "</i>"
@make_bold
@make_italic
def hello():
return "hello world"
print("\n========== Execution ==========")
print(hello())
출력은 다음과 같습니다.
========== Definition ==========
make_italic
make_bold
========== Execution ==========
exec_bold
exec_italic
<b><i>hello world</i></b>
저는 이것이 파이썬의 장식가들의 주문과 그것이 어떻게 처리되는지에 대해 좀 더 조명하기를 바랍니다.
언급URL : https://stackoverflow.com/questions/27342149/decorator-execution-order
'source' 카테고리의 다른 글
| Spring Boot 2.0.x로 마이그레이션할 때 글로벌 CORS 구성이 중단됨 (0) | 2023.07.16 |
|---|---|
| Excel의 다른 워크북을 상대적으로 참조하려면 어떻게 해야 합니까? (0) | 2023.07.16 |
| oAuth2 리소스 서버 애플리케이션 내에서 @WithMock 사용자(@SpringBootTest 포함) 사용 (0) | 2023.07.16 |
| Null이 아닐 경우 입력 매개 변수를 확인하고 SQL Server의 위치에서 사용 (0) | 2023.07.16 |
| R의 숫자에 대한 쉼표 구분 기호? (0) | 2023.07.16 |