I am reading about Python decorators and I have stumbled upon example of nested decorators with arguments. I have tried to understand its call stack, but some steps seems to have no logic for me. Could someone please break down this call stack into little pieces for me? 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() # <--- And the output is: 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 My questions are: Why after "real_decorator end" print, "log_before_and_after_wrapper start" print is executed? Why run_only_between wrapper is called next? Why then execution goes back to the log_before_and_after_wrapper I would be grateful for any help here. EDIT: Debug order Why after returning wrapper in real_decorator code jumps to @run_only_between and than to log_before_and_after()? Shouldn't wrapper() be executed since it was returned by real_decorator? Why after returning wrapper in log_before_and_after, say_something() is being executed and only after that code returns to wrapper in log_before_and_after? Continue reading...