关于python装饰器的介绍和闭包的关系

先来介绍下 装饰器的用途,为什么要使用装饰器

假如有这么个功能,来计算耗时:

def add():

    start_time = time.time()

    time.sleep(3)

    end_time = time.time()

    print("耗时:{}".format(end_time - start_time))

    return None

if __name__ == "__main ":

    add(1, 3)

疑问:会发现,如果我有多个应用需要计时,那就需要写很多的重复代码,这时候就可以使用装饰器来操作:

# 定义一个方法,接收一个函数,在python中一切皆对象,函数也可以用来做参数赋值等

# 需要理解python装饰器加载的过程和闭包

# 新建一个test.py

import time

def time_desc(func):

    print("装饰器")

    start_time = time.time()

    func()

    end_time = time.time()

    print("耗时:{}".format(end_time - start_time))

    # return a + b

@time_desc

def add():

    

    time.sleep(3)

    

    return None

python test.py 运行后,发现函数time_desc,执行了,控制台输入了日志

装饰器

耗时:3.000149965286255

耗时:3.000149965286255

我们并没有运行 time.desc 方法,那它为什么执行了呢? 

事实证明了,在执行或者调用了这个模块里有装饰器,那python的这个@语法糖就直接运行了这个函数,所以我们才需要把

装饰器,写成闭包的形式

改写成:

import time

def time_desc(func):

    def wrapper():

        print("装饰器")

        start_time = time.time()

        func()

        end_time = time.time()

        print("耗时:{}".format(end_time - start_time))

    return wrapper  # 注意 此处不是 wrapper() 不是调用 

@time_desc

def add():

    time.sleep(3)

    return None

还有需要注意:

1、经语法糖@装饰器后,返回的其实是wrapper,如果你调用 add() 其实是执行了装饰器 wrapper方法,

2、如果add(a,b) 有参数的话,那装饰器 wrapper(*args, **kwargs),来解决参数问题


            
            

本博客源码Github地址:

https://github.com/whisnos/myblog

请随手给个star,谢谢!

打赏

评论