Python 装饰器的程序执行顺序

问题提出

在之前的文章中,我们写了下边的代码:

def func(f):
    print("func()")
 
    def func1(*args, **kwargs):
        print("front func1()")
 
        f(*args, **kwargs)
 
        print("behind func1()")
 
    return func1
 
@func
def func2(ch1 = "here",ch2 = " here"):
    print(ch1,ch2,"func2()")
 
@func
def func3(ch = "here"):
    print(ch,"func2()")
 
func2("hello","world")
# func()
# front func1()
# hello world func2()
# behind func1()
 
func3("hello")
# func()
# front func1()
# hello func2()
# behind func1()

我们本以为会出现程序中的结果,但是最后的运行结果却是:

func()
func()
front func1()
hello world func2()
behind func1()
front func1()
hello func2()
behind func1()

这跟我们预想的结果不同,那这是为什么呢?

装饰器的程序执行顺序

这里我们仍然以上边的程序为例,看一下装饰器的程序执行顺序。

print("frist print")

def func(f):
    print("1:func()")

    def func1(*args, **kwargs):
        print("front func1()")

        f(*args, **kwargs)

        print("behind func1()")

    print("2:func()")
    return func1


print("second print")


@func
def func2(ch1="here", ch2=" here"):
    print(ch1, ch2, "func2()")


print("third print")
if __name__ == "__main__":
    print("__main__")
    func2("hello", "world")

执行后的结果为:

frist print
second print
1:func()
2:func()
third print
__main__
front func1()
hello world func2()
behind func1()

我们来看程序的执行顺序,首先是:

print("frist print")

直接输出,这点没有疑问。接着:

def func(f):

上边是函数 func 的函数定义,自然是跳过执行内部语句。接着:

print("second print")

正常输出,没有疑问。接着:

@func
def func2(ch1="here", ch2=" here"):
    print(ch1, ch2, "func2()")

这里我们分语句看,首先是:

@func

没有输出,然后是:

def func2(ch1="here", ch2=" here"):

在执行该条语句时,程序进行了跳转:

def func(f):
    print("1:func()")

    def func1(*args, **kwargs):
        print("front func1()")

        f(*args, **kwargs)

        print("behind func1()")

    print("2:func()")
    return func1

程序跳转至函数 func 内部,完成装饰器定义。在跳转过程中,会输出:

1:func()
2:func()

但对于函数 func 中嵌套的函数 func1 却并不执行内部语句,只完成函数定义。然后返回函数句柄,跳出该段程序,回到:

def func2(ch1="here", ch2=" here"):

这里,函数继续执行,但却跳过

print(ch1, ch2, "func2()")

直接执行:

print("third print")
if __name__ == "__main__":
    print("__main__")

输出:

third print
__main__

然后就到了函数 func2 的执行语句:

func2("hello", "world")

在此语句中,程序执行又发生了跳转,跳转至:

def func1(*args, **kwargs):
    print("front func1()")

    f(*args, **kwargs)

    print("behind func1()")

执行函数体,输出为:

front func1()

接着执行函数 f,其中函数 f 为装饰器定义时的函数句柄,即为函数 func2,因此会发生跳转执行:

print(ch1, ch2, "func2()")

输出:

hello world func2()

重新返回到函数 func1 的语句体中,输出:

behind func1()

再返回到 “__main__” 中,整个装饰器函数运行完毕。

重点就是,在装饰器定义的时候,会将被修饰函数句柄作为参数传递进入装饰器,因此会出现执行函数 func 中的语句的现象,然后返回嵌套函数句柄,完成装饰器定义。而这就是输出结果跟我们预想有所不同的原因了。

发布了77 篇原创文章 · 获赞 5 · 访问量 4917

猜你喜欢

转载自blog.csdn.net/SAKURASANN/article/details/102997862
今日推荐