关于python中装饰器的@语法糖相关问题

关于python中装饰器的@语法糖相关问题

源代码:

import time


def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is ', stop_time-start_time)
    return wrapper


@timmer
def func1():
    print('func1')
    time.sleep(1)

func1()

运行结果:

func1
the func run time is  1.0006778240203857

关于语法糖@timmer的解释,我在网上看了很多文章,都没有解释清楚。基本上都是说@timmer相当于func1 = timmer(func1)。这里就要抠字眼了。‘相当于’,也就是说@timmer并不等于func1 = timmer(func1)。下面代码证实了我的猜想:

import time


def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is ', stop_time-start_time)
    return wrapper

func1 = timmer(func1)
def func1():
    print('func1')
    time.sleep(1)

func1()

运行结果:

NameError: name 'func1' is not defined

分析:首先明白2点:
1、python中程序自上而下执行
2、python是解释型语言,编译和执行是同时进行。
上面代码执行过程:
首先定义timmer()函数,所谓定义,就是将timmer()这个函数的代码块存到内存中。、timmer的代码块包括:

def wrapper():
    start_time = time.time()
    func()
    stop_time = time.time()
    print('the func run time is ', stop_time-start_time)
return wrapper

这里我要说明一下func()。在个代码块中的func()并没有任何意义存在,只是将func()这个名字写到内存。
然后执行func1 = timmer(func1),这个语句分2步。
第一步先执行timmer(func1)。
第二步将timmer(func1)返回值赋值给func1。
首先看第一步,timmer(func1),func1作为实际参数传入timmer()函数中。既然是实际参数,就应该是实实在在的存在着。我们发现func1 = timmer(func1)确实发现了func1函数的定义。但是为什么报错呢?请记住,python是边编译边执行,在执行到timmer(func1)时,先对timmer(func1)进行编译,然后在执行。解释器在编译的时候,发现,在func1 = timmer(func1)之前,内存里并没有保存func1函数的任何信息。为什么呢?因为程序自上而下执行,只有执行完func1 = timmer(func1),才会去执行定义func1函数,也就是将func1函数代码块写到内存。所以才会报错,没有发现func1。按照这个报错的信息,我尝试着把func1 = timmer(func1)放到了定义func1函数之后:

import time

def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is ', stop_time-start_time)
    return wrapper

def func1():
    print('func1')
    time.sleep(1)

func1 = timmer(func1)
func1()

运行结果:

func1
the func run time is  1.0006778240203857

发现这样运行的结果和使用@timmer语法糖运行结果一样,所以我的疑问就来了,@timmer实现的机制到底是什么?在python中到底是怎么运行的?希望有专业人士帮我解答一下

猜你喜欢

转载自blog.csdn.net/Hao_jiu/article/details/84110463