zoukankan      html  css  js  c++  java
  • Python3学习笔记(十三):装饰器

    装饰器就是一个闭包,它的主要作用是在不改变原函数的基础上对原函数功能进行扩展。

    我们先来写一个简单的函数:

    from time import sleep
    
    
    def foo():
        print("Hello World!")
        sleep(2)

    现在我们要对这个函数加一些功能,比如说打印这个函数的执行时间

    有人说,这还不简单啊,直接修改foo函数呢,确实,这是最简单的一种方法。但是在我们实际工作中,有时候是不能对调用的函数进行修改的,那该怎么办呢?

    我们可以重新写个打印时间的函数去调用foo函数啊,比如:

    import time
    from time import sleep
    
    def foo():
        print("Hello World!")
        sleep(2)
    
    def show_time(func):
        start_time = time.time()
        func()
        end_time = time.time()
        print(end_time - start_time)

    调用:

    show_time(foo)
    
    # 输出:
    Hello World!
    2.0000178813934326

    很好,确实是在不修改foo函数的基础上实现了需求,但是。。。。。有个大问题,改变了函数的调用方式,前面是调用foo()的,现在需要修改成调用show_time()。

    看来这种方法也不行。

    这个时候就是闭包大展身手的机会了

    import time
    from time import sleep
    
    def foo():
        print("Hello World!")
        sleep(2)
    
    def show_time(func):
        def inner():
            start_time = time.time()
            func()
            end_time = time.time()
            print(end_time - start_time)
        return inner
    
    #  调用
    foo = show_time(foo)
    foo()
    
    # 输出
    Hello World!
    2.000027656555176

    到这里已经完美地实现了我们的需求,这就是装饰器。装饰器有个高大上的写法,就是装饰器符号@

    上面的代码我们修改成用装饰器符号@来写:

    import time
    from time import sleep
    
    def show_time(func):
        def inner():
            start_time = time.time()
            func()
            end_time = time.time()
            print(end_time - start_time)
        return inner
    
    @show_time    # 其实就相当于foo = show_time(foo)
    def foo():
        print("Hello World!")
        sleep(2)
    
    # 调用
    foo()

    @show_time的作用就是执行foo()时,跳转到去执行inner(),如下图:

    被装饰函数的参数

    如果被装饰的函数有形参,那么在装饰器函数中该怎么写呢?

    import time
    from time import sleep
    
    
    def show_time(func):
        def inner(*x):
            start_time = time.time()
            func(*x)
            end_time = time.time()
            print(end_time - start_time)
        return inner
    
    
    @show_time
    def add(*args):
        sum = 0
        for arg in args:
            sum += arg
        print(sum)
        sleep(2)
    
    
    add(3, 5)

    装饰器函数参数

    有些时候我们可能需要对不同的被装饰函数加些不同的功能,比如需要对某些函数加上日志打印,那该怎么做呢?

    import time
    from time import sleep
    
    
    def logger(flag="false"):
        def show_time(func):
            def inner(*x):
                start_time = time.time()
                func(*x)
                end_time = time.time()
                print(end_time - start_time)
                if flag == "true":
                    print("打印日志记录")
            return inner
        return show_time
    
    
    @logger("true")   # 打印日志记录
    def add(*args):
        sum = 0
        for arg in args:
            sum += arg
        print(sum)
        sleep(2)
    
    @logger()   # 不需要打印日志记录
    def foo():
        print("Hello World!")
        sleep(2)
  • 相关阅读:
    Charles抓包工具
    JQuery 实现表单验证,所有验证通过方可提交
    卡巴斯基注册信息清除
    Nginx 404 Not Found 解决办法
    php mysql 多表查询之子查询语句
    搜狗拼音、QQ拼音输入法、2345拼音输入法、百度输入法 、手心输入法对比。(个人体会)
    Notepad++使用-如何导出/导入配置文件
    深蓝词库转换2.4版发布,支持最新的搜狗用户词库备份bin格式
    网站更换服务器,百度站长后台抓取诊断时间
    阿里云代金券领取
  • 原文地址:https://www.cnblogs.com/eastonliu/p/9130021.html
Copyright © 2011-2022 走看看