• Python装饰器(你想知道的这里都有)


    【导读】:装饰器(Decorators)是 Python 的一个重要部分。简单地说:它们是修改其他函数的功能的函数。有助于让我们的代码更简短,也更Pythonic(Python范儿)。很多Pythoner不知道在哪儿使用它们,哪些区域里装饰器可以让代码更简洁。通过本文的学习让你理解并学会装饰器,让你更Pythonic!来一起学习吧。​

    1、装饰器的定义

     

    就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数。装饰器的功能特点:

    1、不修改已有函数的源代码

    2、不修改已有函数的调用方式

    3、给已有函数增加额外的功能

    4、闭包和装饰器的区分:

    如果闭包函数的参数有且只有一个,并且是函数类型,那么这个闭包函数称之为装饰器。写代码要遵循开放封闭原则,它规定已经实现的功能代码不允许被修改,但可以被扩展。

    2、装饰器的示例代码

     # 定义装饰器

    def decorator(func):
        def inner():
            # 在内部函数里面对已有函数进行装饰
            print('已添加登录认证')
            func()
        return inner
    def comment():
        print('发表评论')
    # 调用装饰器对已有函数进行装饰,左边的comment=inner
    comment = decorator(comment) # 调用方式不变

    comment()

      

    3、装饰器的语法糖写法

     

    如果有多个函数都需要添加登录验证的功能,每次都需要编写func = decorator(func)这样代码对已有函数进行装饰,这种做法还是比较麻烦。

    Python给提供了一个装饰函数更加简单的写法,那就是语法糖,语法糖的书写格式是: @装饰器名字,通过语法糖的方式也可以完成对已有函数的装饰。

    # 定义装饰器
    
    def decorator(func):
    
        def inner():
    
            # 在内部函数里面对已有函数进行装饰
    
            print('已添加登录认证')
    
            func()
    
        return inner
    
    @decorator  # comment = decorator(comment) 装饰器语法糖对该代码进行了封装 左边comment=inner
    
    def comment():
    
        print('发表评论')
    
    # 调用方式不变
    
    comment()
    

      

    4、装饰器的执行时机

     

    当前模块加载完成以后,装饰器会立即执行,对已有函数进行装饰。

    # 定义装饰器
    
    def decorator(func):
    
        print('装饰器执行了')
    
     
    
        def inner():
    
            # 在内部函数里面对已有函数进行装饰
    
            print('已添加登录认证')
    
            func()
    
        return inner
    
    @decorator  # comment = decorator(comment) 装饰器语法糖对该代码进行了封装 左边comment=inner
    
    def comment():
    
        print('发表评论')
    

      

    5、装饰器的使用

     

    5.1 装饰器的使用场景

        1.函数执行时间的统计。

        2.输出日志信息。

    5.2 装饰器实现已有函数执行时间的统计

    import time
    
     
    
     
    
    def decorator(func):
    
        def inner():
    
            # 获取时间距离1970-1-1 0:0:1的时间差
    
            begin = time.time()
    
            func()
    
            end = time.time()
    
            result = end - begin
    
            print(f'函数执行完成耗时:{result}')
    
     
    
        return inner
    
     
    
     
    
    @decorator
    
    def work():
    
        for i in range(10000):
    
            print(i)
    
     
    
     
    
    work()
    

      

    6、通用装饰器的使用

    通用装饰器:可以装饰任意类型的函数。使用装饰器装饰已有函数的时候,内部函数的类型和要装饰的已有函数的类型保持一致。

    6.1 装饰带有参数的函数

    def decorator(func):
    
        def inner(num1, num2):
    
            print('正在努力执行加法计算')
    
            func(num1, num2)
    
     
    
        return inner
    
     
    
     
    
    @decorator
    
    def add_num(num1, num2):
    
        result = num1 + num2
    
        print(f'结果为:{result}')
    
     
    
     
    
    add_num(1, 2)
    

      

    6.2 装饰带有参数、返回值的函数

     

    def decorator(func):
    
        def inner(num1, num2):
    
            print('正在努力执行加法计算')
    
            num = func(num1, num2)
    
            return num
    
     
    
        return inner
    
     
    
     
    
    @decorator
    
    def add_num(num1, num2):
    
        result = num1 + num2
    
        return result
    
     
    
     
    
    result = add_num(1, 2)
    
    print(f'结果为:{result}')
    

      

    6.3 装饰带有不定长参数、返回值的函数

     

    def decorator(func):
    
        def inner(*args, **kwargs):
    
            print('正在努力执行加法计算')
    
            # *args:把元组里面的每一个元素,按照位置参数的方式进行传参
    
            # **kwargs:把字典里面的每一个键值对,按照关键字的方式进行传参
    
            num = func(*args, **kwargs)
    
            return num
    
     
    
        return inner
    
     
    
     
    
    @decorator
    
    def add_num(*args, **kwargs):
    
        result = 0
    
        for value in args:
    
            result += value
    
        for value in kwargs.values():
    
            result += value
    
        return result
    
     
    
     
    
    result = add_num(1, 2, a=3)
    
    print(f'结果为:{result}')
    

      

    7、多个装饰器的使用

    多个装饰器的装饰过程:由内到外的一个装饰过程,先执行内部的装饰器,在执行外部的装饰器。

    def make_div(func):
        print('make_div装饰器执行了')
        def inner():
            result = '<div>' + func() + '</div>'
            return result
        return inner
    def make_p(func):
        print('make_p装饰器执行了')
        def inner():
            result = '<p>' + func() + '</p>'
            return result
        return inner
    # 原理剖析:content = make_div(make_p(content))
    # 分布拆解:content = make_p(content),内部装饰器完成,content = make_p.inner
    #          content = make_div(make_p.inner)
    @make_div
    @make_p
    def content():
        return '人生苦短,我用python'
    c = content()
    print(c)make_p装饰器执行了

    make_p装饰器执行了
    make_div装饰器执行了

    <div><p>人生苦短,我用python</p></div>

    8、带有参数的装饰器

    带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数,语法格式: @装饰器(参数,…)。使用带有参数的装饰器,其实是在装饰器外面又包裹了一个函数,使用该函数接收参数,返回是装饰器,因为 @ 符号需要配合装饰器实例使用。

    def return_decorator(flag):
    
        # 装饰器只能接收一个参数并且是函数类型
    
        def decorator(func):
    
            def inner(a, b):
    
                if flag == '+':
    
                    print('正在努力执行加法计算')
    
                elif flag == '-':
    
                    print('正在努力执行减法计算')
    
                func(a, b)
    
     
    
            return inner
    
     
    
        # 当调用函数的时候可以返回一个装饰器decorator
    
        return decorator
    
     
    
     
    
    @return_decorator('+')  # decorator = return_decorator('+'), @decorator => add_num = decorator(add_num)
    
    def add_num(a, b):
    
        result = a + b
    
        print(result)
    
     
    
     
    
    @return_decorator('-')
    
    def sub_num(a, b):
    
        result = a - b
    
        print(result)
    
     
    
     
    
    add_num(1, 2)
    
    sub_num(1, 2)
    

      

    9、类装饰器的使用

    类装饰器:使用类装饰已有函数

    class MyDecorator(object):
    
        def __init__(self, func):
    
            self.__func = func
    
     
    
        # 实现__call__方法,表示对象是一个可调用对象,可以像调用函数一样进行调用
    
        def __call__(self, *args, **kwargs):
    
            # 对已有函数进行封装
    
            print('马上就有下班啦')
    
            self.__func()
    
     
    
     
    
    @MyDecorator  # @MyDecorator => show = MyDecorator(show)
    
    def show():
    
        print('快要下雪啦')
    
     
    
     
    
    # 执行show,就相当于执行MyDecorator类创建的实例对象,show() => 对象()
    
    show()
    

      

    扩展:

    函数之所以能够调用,是因为函数内部实现了 __call__ 方法。

    10、装饰器应用场景

    1、收集函数的操作或错误日志记录。

    2、验证函数的使用权限。

    3、计算函数的运行时间。

    4、在ORM/DB模型操作时,通过属性方法动态地获取关联的数据。

    5、函数数据的缓存。

    6、定制函数的输入和输出(序列化和反序列化)。

    注意:如果你是打算找python高薪工作的话。我建议你多写点真实的企业项目积累经验。不然工作都找不到,当然很多人没进过企业,怎么会存在项目经验呢? 所以你得多找找企业项目实战多练习下撒。如果你很懒不想找,也可以进我的Python交流圈:1156465813。群文件里面有我之前在做开发写过的一些真实企业项目案例。你可以拿去学习,不懂都可以在裙里找我,有空会耐心给你解答下。

    以下内容无用,为本篇博客被搜索引擎抓取使用
    (* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)
    python 是干什么的 零基础学 python 要多久 python 为什么叫爬虫
    python 爬虫菜鸟教程 python 爬虫万能代码 python 爬虫怎么挣钱
    python 基础教程 网络爬虫 python python 爬虫经典例子
    python 爬虫
    (* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)(* ̄︶ ̄)
    以上内容无用,为本篇博客被搜索引擎抓取使用

  • 相关阅读:
    【Codeforces Round #645 (Div. 2) F】 Tasty Cookie
    【Codeforces Round #645 (Div. 2) E】 Are You Fired?
    【Educational Codeforces Round 88 (Rated for Div. 2) C】 Mixing Water
    20191114-4 Beta发布用户使用报告
    20191114-3 Beta阶段贡献分配
    beta发布
    20191107-1 每周例行报告
    beta 2/2 阶段中间产物提交入口
    beta week 2/2 Scrum立会报告+燃尽图 07
    beta week 2/2 Scrum立会报告+燃尽图 06
  • 原文地址:https://www.cnblogs.com/shuchongzeishuai/p/13935909.html
Copyright © 2020-2023  润新知