source

데코레이터실행순서

itover 2023. 7. 16. 19:30
반응형

데코레이터실행순서

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

반응형