• 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

    在这里插入图片描述

    装饰器的多重使用

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

  • 相关阅读:
    任务清单小功能的实现(任务的增、删、改、查、存储)使用Vue实现
    微信公众号迁移详细步骤
    第二十二课,实例化(instancing)
    开发思维——【小项目玩出步骤】——移动端适配和项目老大做设计
    SpringMvc常用注解
    创建成本中心其他前提及后续配置
    Yakit工具篇:爆破与未授权检测的使用
    正确理解党籍和党龄;入党和转正时间
    【单细胞高级绘图】10.KEGG富集结果的圆圈图
    React项目首页中用canvas实现星空
  • 原文地址:https://blog.csdn.net/qq_45583898/article/details/125860873