• Python高级语法-装饰器(Python语法糖)


    参考:https://blog.csdn.net/zhouchen1998/article/details/82933893

    起因:在探究pytorch官方的fasterrcnn实现中发现使用装饰器。特意探究。

    在这里插入图片描述

    高阶函数

    在python语言中,参数含有函数名的函数称之为高阶函数。(此时调用的函数不加参数,也就是说没有括号紧跟)

    装饰器是什么

    装饰器 <== 高阶函数 + 嵌套函数

    在不改变源代码的基础上扩展函数需要的新需求,这就是装饰器。(不改变函数源代码,这也是装饰器最基本的原则)

    装饰器,它本身也就是一个函数,应用高阶函数实现。

    使用时一般把被装饰的函数的内存地址当参数传入装饰器函数体,通过参数调用被装饰的函数,获得或者修改其属性。

    装饰器的使用

    一般认为,装饰器使用遵循一定格式,即:高阶函数+高阶函数内嵌套函数。

    假设有一个需求,我要知道正在运行什么函数,在运行时输出。

    有一个比较粗暴的方法。

    # 可以直接在函数中定义
    def func1():
        print(func1.__name__)
        pass
    
    
    def func2():
        print(func2.__name__)
        pass
    
    
    if __name__ == '__main__': #在另一篇文章提到这个,即保证只在该程序运行,不会在import中运行以下。http://t.csdn.cn/U3H1i
        func1()
        func2()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这一定是对的,但是不自然就想到两个字“封装”,虽然这和装饰器大相径庭,但是两个概念确实有相通之处。

    按照装饰器原则,可以这样写。
    这里需要注意的是,在装饰器定义的时候,return时不加括号。具体原因见:http://t.csdn.cn/uMdqd

    # 使用装饰器
    def zhuang_shi_qi(func):
        def out():
            func()
            print(func.__name__)
        return out  # 这里的'()'会导致报错'NoneType' object is not callable
                    # 只要去掉out后面的括号即可解决问题
    
        def whatever():
            pass
        return whatever
    
    
    @zhuang_shi_qi
    def func1():
        pass
    
    
    @zhuang_shi_qi
    def func2():
        pass
    
    
    if __name__ == '__main__':
        func1() #如果前面加了括号,这里将会不可调用,虽然去掉这里的括号也可以,但与“装饰器不改变函数调用的方式”原则相违背。
        func2()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    成功实现该功能
    在这里插入图片描述

    装饰器的进一步使用

    在之前的这个小实验中,基本上了解了装饰器的用途和写法,然而不是所有的函数都向func1这样简单,无参数。

    对于含不定参数的函数,参数由收集参数获取。

    装饰器 <== 高阶函数 + 嵌套函数

    def zhuang_shi_qi(func):
        def out(*args, **kwargs): # args为何物见http://t.csdn.cn/xfM7a
            func(*args, **kwargs)
            print(func.__name__)
        return out
    
    
    @zhuang_shi_qi
    def func1(a, b):
        print(a+b)
    
    
    @zhuang_shi_qi
    def func2(a, b, c):
        print(a+b+c)
    
    
    if __name__ == '__main__':
        func1(1, 2)
        func2(1, 2, 3)
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    装饰器的多重使用

    不同的装饰器是可以给同一个函数装饰的,会从最后一个装饰器开始执行到第一个装饰器,再执行函数本身。

  • 相关阅读:
    Java线程周期
    lvm磁盘管理
    Pytest 源码解读 [1] - [pluggy] 核心设计理念浅读
    虚拟机(VM)监控工具
    基于FPGA的自动白平衡算法实现
    指纹面容识别登录流程概述
    dd命令:用于读取、转换并输出数据
    重装系统电脑黑屏开不了机如何处理
    11个程序员必备简捷开发辅助工具
    为后续的PCBA生产更为顺畅,这篇盖/露PAD怎么选的文章不容错过
  • 原文地址:https://blog.csdn.net/qq_45583898/article/details/125860873