• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

装饰器相关使用

武飞扬头像
黑马蓝汐
帮助1

每日分享:

生活总是让我们遍体鳞伤,可是后来,那些受伤的地方一定会变成我们最强壮的地方。

目录

一、装饰器

1. 装饰器的定义

2. 装饰器示例代码

3. 装饰器的语法糖写法

二、装饰器的使用

1. 装饰器的使用场景

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

三、通用装饰器的使用

1. 装饰带有参数的函数

2. 装饰带有参数和返回值的函数

3. 装饰带有不定长参数的函数

4. 通用装饰器(不定长参数以及有返回值)

四、多个装饰器的使用

五、带有参数的装饰器

六、类装饰器


一、装饰器

1. 装饰器的定义

就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数

装饰器的功能特点:

  1. 不修改已有函数的源代码
  2. 不修改已有函数的调用方式
  3. 给已有函数增加额外的功能

2. 装饰器示例代码

  1.  
    # 装饰器实质上就是闭包,怎么判断装饰器:当闭包函数只有一个参数,并且该参数是函数类型,那么这就是一个装饰器
  2.  
    def func_out(func):
  3.  
    def inner():
  4.  
    print('登录了吗,就说话?')
  5.  
    func()
  6.  
    print('赶快登录')
  7.  
    return inner
  8.  
     
  9.  
     
  10.  
    def comment():
  11.  
    print("发表评论")
  12.  
     
  13.  
     
  14.  
    # 为了保证调用时名称不变,将闭包对象命名为函数同名
  15.  
    comment = func_out(comment)
  16.  
    comment()
学新通
  • 闭包函数有且只有一个参数,必须是函数类型,这样定义的函数才是装饰器
  • 写代码要遵循开放封闭原则,它规定已经实现的功能代码不允许被修改,但可以被扩展

学新通

3. 装饰器的语法糖写法

如果有多个函数都需要拓展功能,每次都需要编写comment = func_out(comment)这样的代码对已有函数进行装饰,就会比较麻烦。

所以就有了语法糖,其书写格式为:@装饰器名字

通过语法糖的方式也可以完成对已有函数的装饰

  1.  
    # 装饰器实质上就是闭包,怎么判断装饰器:当闭包函数只有一个参数,并且该参数是函数类型,那么这就是一个装饰器
  2.  
    def func_out(func):
  3.  
    def inner():
  4.  
    print('登录了吗,就说话?')
  5.  
    func()
  6.  
    print('赶快登录')
  7.  
    return inner
  8.  
     
  9.  
     
  10.  
    @ func_out
  11.  
    def comment():
  12.  
    print("发表评论")
  13.  
     
  14.  
     
  15.  
    # 为了保证调用时名称不变,将闭包对象命名为函数同名
  16.  
    # comment = func_out(comment)
  17.  
    comment()
学新通

学新通

可以发现,结果一模一样

说明:

  • @装饰器名 就等价于 comment = func_out(comment)
  • 装饰器的执行时间是加载模块时立即执行

二、装饰器的使用

1. 装饰器的使用场景

  1. 函数执行时间的统计
  2. 输入日志信息

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

  1.  
    import time
  2.  
     
  3.  
     
  4.  
    def decorator(func):
  5.  
    def inner():
  6.  
    begin = time.time()
  7.  
    func()
  8.  
    end = time.time()
  9.  
    print("函数运行的时间:", end-begin)
  10.  
    return inner
  11.  
     
  12.  
     
  13.  
    @decorator
  14.  
    def work():
  15.  
    for i in range(10000):
  16.  
    print(i)
  17.  
     
  18.  
     
  19.  
    work()
学新通

学新通

所以,装饰器可以在不改变函数源代码及调用方式的前提下,扩展函数功能

三、通用装饰器的使用

1. 装饰带有参数的函数

  1.  
    def decorator(func):
  2.  
    def inner(a, b):
  3.  
    print("正在努力计算中...")
  4.  
    func(a, b)
  5.  
    return inner
  6.  
     
  7.  
     
  8.  
    @decorator
  9.  
    def add_num(num1, num2):
  10.  
    result = num1 num2
  11.  
    print(result)
  12.  
     
  13.  
     
  14.  
    add_num(1, 2)
  15.  
     
  16.  
     
学新通

学新通

2. 装饰带有参数和返回值的函数

  1.  
    # --------------------装饰器装饰带有返回值的函数----------------------
  2.  
    def decorator(func):
  3.  
    def inner(a, b):
  4.  
    print("正在努力计算中...")
  5.  
    sum1 = func(a, b)
  6.  
    return sum1
  7.  
    return inner
  8.  
     
  9.  
     
  10.  
    @decorator
  11.  
    def add_num(num1, num2):
  12.  
    result = num1 num2
  13.  
    return result
  14.  
     
  15.  
     
  16.  
    sum2 = add_num(1, 2)
  17.  
    print(sum2)
学新通

学新通

3. 装饰带有不定长参数的函数

  1.  
    # --------------------装饰器装饰带有不定参数的函数---------------------------------
  2.  
    def decorator(func):
  3.  
    def inner(*args, **kwargs):
  4.  
    print("正在努力计算中...")
  5.  
    func(*args, **kwargs)
  6.  
    return inner
  7.  
     
  8.  
     
  9.  
    # *args:把元组里面的每一个元素,按照位置参数的方式进行传参
  10.  
    # **kwargs:把字典里面的每一个键值对,按照关键字的方式进行传参
  11.  
    @decorator
  12.  
    def add_num(*args, **kwargs):
  13.  
    result = 0
  14.  
    for value in args:
  15.  
    result = value
  16.  
    for value in kwargs.values():
  17.  
    result = value
  18.  
    print(result)
  19.  
     
  20.  
     
  21.  
    add_num(1, 2, a=3)
学新通

学新通

4. 通用装饰器(不定长参数以及有返回值)

  1.  
    # --------------------通用装饰器---------------------------------
  2.  
    def decorator(func):
  3.  
    def inner(*args, **kwargs):
  4.  
    print("正在努力计算中...")
  5.  
    num = func(*args, **kwargs)
  6.  
    return num
  7.  
    return inner
  8.  
     
  9.  
     
  10.  
    @decorator
  11.  
    def show():
  12.  
    return "你好!"
  13.  
     
  14.  
     
  15.  
    info = show()
  16.  
    print(info)
学新通

学新通

通过以上几类装饰器的书写,可以发现:

装饰器的内部函数inner与要装饰的函数保持一致即可,即装饰函数有参数,inner就有参数;装饰函数有返回值,inner就有返回值

四、多个装饰器的使用

  1.  
    def add_p(func):
  2.  
    def inner():
  3.  
    result = "<p>" func() "</p>"
  4.  
    return result
  5.  
    return inner
  6.  
     
  7.  
     
  8.  
    def add_div(func):
  9.  
    def inner():
  10.  
    result = "<div>" func() "</div>"
  11.  
    return result
  12.  
    return inner
  13.  
     
  14.  
     
  15.  
    @add_div
  16.  
    @add_p
  17.  
    def content():
  18.  
    return "人生苦短,我学python"
  19.  
     
  20.  
     
  21.  
    print(content())
学新通

学新通

说明:

  • 多个装饰器的装饰:离函数最近的装饰器先装饰,然后外面的装饰器再对装饰后的函数进行装饰

五、带有参数的装饰器

带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数

语法格式:@装饰器(参数...)

在装饰器外面包裹上一个函数,让最外面的函数接收参数,返回的是装饰器

  1.  
    def logging(flag):
  2.  
    def decorator(func):
  3.  
    def inner(a, b):
  4.  
    if flag == " ":
  5.  
    print("正在进行加法运算...")
  6.  
    elif flag == "-":
  7.  
    print("正在进行减法运算...")
  8.  
    result = func(a, b)
  9.  
    return result
  10.  
    return inner
  11.  
    return decorator
  12.  
     
  13.  
     
  14.  
    @logging(" ")
  15.  
    def add(a, b):
  16.  
    result = a b
  17.  
    return result
  18.  
     
  19.  
     
  20.  
    @logging("-")
  21.  
    def sub(a, b):
  22.  
    result = a - b
  23.  
    return result
  24.  
     
  25.  
     
  26.  
    print(add(1, 2))
  27.  
    print(sub(1, 3))
学新通

学新通

使用带有参数的装饰器,其实是在装饰器外面又包裹了一个函数,使用该函数接收参数,返回装饰器(@符号必须配合装饰器使用)

六、类装饰器

装饰器还有一种特殊的用法就是类装饰器,就是通过定义一个类来装饰函数

  1.  
    class Check(object):
  2.  
     
  3.  
    def __init__(self, func):
  4.  
    # 初始化操作在此完成(将func设为私有)
  5.  
    self.__func = func
  6.  
     
  7.  
    # 实现call方法,表示对象是一个可调用对象,可以像调用函数一样进行调用
  8.  
    def __call__(self, *args, **kwargs):
  9.  
    # 添加装饰功能
  10.  
    print("请先登录")
  11.  
    self.__func()
  12.  
     
  13.  
     
  14.  
    @Check
  15.  
    def comment():
  16.  
    print('发表评论')
  17.  
     
  18.  
     
  19.  
    comment()
学新通

学新通

说明:

  • @Check等价于comment = Check(comment),所以需要提供一个init方法,并多增加一个func参数
  • 要想类的实例对象能够像函数一样调用,需要在类里面使用call方法,把类的实例变成可调用对象,也就是说可以像函数一样调用
  • 在call方法里对func函数进行装饰,可以添加额外的功能

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgiceka
系列文章
更多 icon
同类精品
更多 icon
继续加载