Python调用堆栈中带参数的嵌套装饰器

Python调用堆栈中带参数的嵌套装饰器,python,python-decorators,Python,Python Decorators,我正在阅读有关Python装饰器的文章,偶然发现了带有参数的嵌套装饰器示例。 我试图理解它的调用堆栈,但有些步骤对我来说似乎没有逻辑。有人能帮我把这个呼叫堆栈分解成小块吗 from datetime import datetime def log_before_and_after(func): def wrapper(): print("log_before_and_after_wrapper start") result = fu

我正在阅读有关Python装饰器的文章,偶然发现了带有参数的嵌套装饰器示例。 我试图理解它的调用堆栈,但有些步骤对我来说似乎没有逻辑。有人能帮我把这个呼叫堆栈分解成小块吗

from datetime import datetime


def log_before_and_after(func):
    def wrapper():
        print("log_before_and_after_wrapper start")
        result = func()
        print("log_before_and_after_wrapper end")
        return result

    return wrapper


def run_only_between(_from=7, _to=22):
    print("run_only_between start")

    def real_decorator(func):
        print("real_decorator start")

        def wrapper():
            print("run_only_between_wrapper start")
            if _from <= datetime.now().hour < _to:
                func()
                print("run_only_between_wrapper end")
            else:
                print("run_only_between_wrapper end")

        print("real_decorator end")
        return wrapper

    print("run_only_between end")
    return real_decorator


@log_before_and_after
@run_only_between(7, 22)
def say_something():
    print("Hello!!")


say_something()  # <---
我的问题是: 为什么在执行
“real\u decorator end”
打印之后、
“log\u before\u和\u after\u wrapper start”
打印

为什么下一步调用包装器之间的
run\u only\u

那么为什么exexution返回到包装器之前和之后的
log\u

如果能在这里得到任何帮助,我将不胜感激

编辑:

为什么在
real\u decorator
code中返回
wrapper
后,代码会在
之间跳到
@run\u only\u,而不是在
之前和之后()记录?由于它是由
real\u decorator
返回的,所以不应该执行
wrapper()


为什么在
log\u before\u和\u after
中返回
wrapper
后,
say\u something()
会被执行,并且只有在
log\u before\u和\u after
中返回
wrapper
后,代码才会被执行?

我认为如果您在调试模式下运行代码,并逐步执行代码,您的工作会更轻松。然后您可以看到代码是如何跳转的。前两个方法是方法定义。那里还没有采取任何行动。您的第三个方法是一个方法定义,但它正在被修饰。这是你的第一张照片。(方法尚未执行!)即使在
run\u中没有执行所有打印命令,也只执行
之间的命令。只返回外部打印和新的装饰方法等。这很难用语言表达。@Tin Nguyen使用调试器是我脑海中第一件想到的事情,这就是我为什么发布这个问题的原因。代码之间的一些“跳跃”对我来说是完全不清楚的。如果有人能一步一步地向我解释调用堆栈,那就太神奇了。我知道有很多跳跃。我明白为什么会发生这些跳跃。在调试模式下运行时,如果指出一些不理解和看不到的跳转,会更容易。我会解释那些具体的跳跃。但是我不会解释所有的跳转,因为这个解释太复杂和混乱了。@TinNguyen我已经上传了调试执行顺序并添加了我的问题,你能看一下吗?我不知道如何更直观地解释它。如果你只看一个装饰师,你会更容易理解它。
run_only_between start
run_only_between end
real_decorator start
real_decorator end
log_before_and_after_wrapper start
run_only_between_wrapper start
Hello!!
run_only_between_wrapper end
log_before_and_after_wrapper end