1、装饰器的本质

装饰器本质上是一个闭包函数,可以让其它函数在不需要任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数。

  • 闭包函数

    1)必须是嵌套函数,即外函数中定义了一个内函数;

    2)内函数引用了外函数作用域中(注意:非全局)的变量;

    3)外函数的返回值是内函数的引用;

    4)检测函数是否为闭包函数:function.__closure__,是闭包,返回一个cell,不是闭包,返回None

  • 函数

    1)什么是函数:组织好的、可重复使用的,用来实现单一或相关联功能的代码段;

    2)函数的优点:函数能提高应用的模块性和代码的重复利用率;

    3)函数的定义:使用def关键字;

    def func():print("Hello, World!")
    

    4)函数的参数:根据函数在定义时和调用时,函数的参数有不同的概念;

    • 定义时:位置参数、默认参数、不定长参数;
    def func(a, b=0, *args, **kwargs):print(f"位置参数:{a}")print(f"默认参数:{b}")print(f"不定长参数:元组{args},字典{kwargs}")
    
    • 调用时:必备参数(必须传)、关键字参数(可传可不传)、不定长参数(可传可不传);
    func("Hello")                            # "Hello" >> a
    func("Hello", b=1)                    # "Hello" >> a, 1 >> b
    func("Hello", 2)                        # "Hello" >> a, 2 >> b
    func("Hello", 2, 3, c="World")  # "Hello" >> a, 2 >> b, 3 >> *args, c="World" >> **kwargs
    

    5)匿名函数:使用lambda关键字,只是一个表达式,不是代码块,逻辑有限;

    add = lambda a, b: a + b
    

    6)变量作用域:LEGB;

    • L:Local,局部作用域;
    • E:Enclosing,闭包函数外的函数中;
    • G:Global,全局作用域;
    • B:Built-in,内建作用域;

    7)有关函数的几个概念;

    • 函数即变量:函数可作为参数,也可作为返回值;
    • 高阶函数:以函数作为参数或返回值的函数,内置函数map()filter()functools包中的reduce()
    • 嵌套函数:函数里定义函数;
    • 嵌套函数中变量的生命周期:正常情况下,一个函数运行结束,函数所有局部对象都会被回收,释放内存。但是闭包是一种特殊情况。闭包中,如果外函数在结束时,外函数作用域中的临时变量被内函数调用,外函数就会将该变量绑定给内函数,然后再结束;

2、装饰器应满足条件

  • 给被装饰函数添加新的功能;
  • 不能改变被装饰函数的代码;
  • 不能改变被装饰函数的调用方式;

3、装饰器的应用场景

  • 插入日志;
  • 性能测试;
  • 事务处理;
  • 缓存、权限校验;

4、装饰器的固定格式

  • 格式1

    def decorator(func):                          # decorator函数中嵌套了inner函数def inner(*args, **kwargs):"""something before func"""f = func(*args, **kwargs)          # 内函数inner调用了外函数decorator作用域中的变量func"""something after func"""return freturn inner                                  # 外函数decorator的返回值是inner(对内函数inner的引用)
    
  • 格式2

    from functools import wrapsdef decorator(func):@wrapsdef wrapper(*args, **kwargs):return func(*args, **kwargs)return wrapper
    

5、装饰器的演进

  • 将被装饰的函数显式传入装饰器,被装饰函数没有参数和返回值;

    import timedef func():print("I'm func.")def timer(f):def inner():start = time.time()f()end = time.time()print(end - start)return innerfunc = timer(func)          # 将函数func作为参数传递给timer装饰器,将返回结果赋值给变量func
    func()                             # func(),即执行了func
    
  • 将被装饰函数放在语法糖下一行,被装饰函数不带参数,没有返回值;

    import timedef timer(f):def inner():start = time.time()f()end = time.time()print(end - start)return inner@timer                    # @timer被称为语法糖,等价于func=timer(func)
    def func():print("I'm func.")func()
    
  • 将被装饰函数放在语法糖下一行,被装饰函数带1个参数,没有返回值;

    import timedef timer(f):def inner(i):start = time.time()f(i)end = time.time()print(end - start)return inner@timer
    def func(x):print(x)func("Hello, World!")
    
  • 将被装饰函数放在语法糖下一行,被装饰函数带2个参数,没有返回值;

    import timedef timer(f):def inner(*args, **kwargs):start = time.time()f(*args, **kwargs)end = time.time()print(end - start)return inner@timer
    def func(x, y):print(f"The first argument is {x}, the second is {y}.")func(2, 24)
    
  • 将被装饰函数放在语法糖下一行,被装饰函数带多个参数,有返回值;

    import timedef timer(f):def inner(*args, **kwargs):start = time.time()r = f(*args, **kwargs)end = time.time()print(end - start)return rreturn inner@timer
    def func(x, y, z=3):print(f"Arguments are {}、{} and {}.")return 'Over'func(1, 2, z=3)
    print(func(1, 2, z=3))
    
  • 带参数的装饰器,被装饰函数不带参数,没有返回值;

    def outer(flag):def decorator(f):def inner(*args, **kwargs):if flag:print("Ahead func")r = f(*args, **kwargs)if flag:print("After func")return rreturn innerreturn decorator@outer(True)
    def func():print("Hello, World!")func()
    
  • 多个装饰器装饰同一个函数,被装饰函数不带参数,没有返回值;

    def decorator1(f):def inner():print('Decorator1, before f')f()print('Decorator1, after f')return innerdef decorator2(f):def inner():print('Decorator2, before f')f()print('Decorator2, after f')return inner@decorator2
    @decorator1
    def func():print("I'm func.")
    

6、装饰器的总结

Python中的装饰器一共有4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类;

  • 函数装饰函数:函数作为参数被传入装饰器函数中;

    def decorator(f):def inner(*args, **kwargs):print(f"function name: {f.__name__}")r = f(*args, **kwargs)return rreturn inner@decorator                    # @decorator 等价于 addition=decorator(addition)
    def addition(x, y):return x + yprint(addition(3, 7))
    
  • 函数装饰类:类作为参数被传入装饰器函数中;

    def decorator(cls):def inner(*args, **kwargs):print(f"class name: {cls.__name__}")return cls(*args, **kwargs)return inner@decorator                     # @decorator 等价于 Func=decorator(Func)
    class Func:def __init__(self, item):self.item = itemdef func(self):print(f"self.a = {self.a}")f = Func('Hello, World!')
    f.func()
    
  • 类装饰函数:函数作为参数被传入装饰器类中;

    class Decorator:def __init__(self, f):self.f = fdef __call__(self, item):print(f"function name: {self.f.__name__}")return self.f(item)@Decorator                    # @Decorator 等价于 func = Decorator(func).__call__
    def func(i):return iprint(func("Hello, World!"))
    
  • 类装饰类:类作为参数被传入装饰器类中;

    class Decorator:def __init__(self, cls):self.cls = clsdef __call__(self, item):print(f"class name: {self.cls.__name__}")return self.cls(item)@Decorator                    # @Decorator 等价于 Func = Decorator(Func).__call__
    class Func:def __init__(self, v):self.v = vdef func(self):print(self.v)f = Func("Hello, World!")
    f.func()

一文搞懂Python知识难点------装饰器相关推荐

  1. python 闭包和装饰器详解_实力讲解,一文读懂Python闭包与装饰器!

    什么是装饰器? 装饰器(Decorator)相对简单,咱们先介绍它:"装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数", ...

  2. 一文搞懂 Python 的 import 机制

    一.前言 希望能够让读者一文搞懂 Python 的 import 机制 1.什么是 import 机制? 通常来讲,在一段 Python 代码中去执行引用另一个模块中的代码,就需要使用 Python ...

  3. python语言语句快的标记是什么_一文搞懂Python程序语句

    原标题:一文搞懂Python程序语句 程序流 Python 程序中常用的基本数据类型,包括: 内置的数值数据类型 Tuple 容器类型 String 容器类型 List 容器类型 自然的顺序是从页面或 ...

  4. python中gbk字符原因报错_不想再被鄙视?那就看进来! 一文搞懂 Python 2 字符编码...

    原标题:不想再被鄙视?那就看进来! 一文搞懂 Python 2 字符编码 程序员都自视清高,觉得自己是创造者,经常鄙视不太懂技术的产品或者QA.可悲的是,程序员之间也相互鄙视,程序员的鄙视链流传甚广, ...

  5. 一文搞懂Python Unittest测试方法执行顺序

    Unittest unittest大家应该都不陌生.它作为一款博主在5-6年前最常用的单元测试框架,现在正被pytest,nose慢慢蚕食. 渐渐地,看到大家更多的讨论的内容从unittest+HTM ...

  6. 不想再被鄙视?那就看进来! 一文搞懂 Python 2 字符编码

    程序员都自视清高,觉得自己是创造者,经常鄙视不太懂技术的产品或者QA.可悲的是,程序员之间也相互鄙视,程序员的鄙视链流传甚广,作为一个Python程序员,自然最关心的是下面这幅图啦 我们项目组一值使用 ...

  7. python中row是什么意思_一文搞懂Python中的yield

    关注公众号「Python七号」,及时 get Python 技能. yield 可以实现生成器,可以实现协程. 什么是生成器,什么是协程,如果还不了解,可以继续往下看,概念可以不懂,只要理解它的作用和 ...

  8. 30例 | 一文搞懂python日期时间处理

    前言 datetime是python的内置模块,用来处理日期和时间. 该模块常用的类有: 类名 功能说明 date 日期对象 time 时间对象 datetime 日期时间对象 timedelta 时 ...

  9. 一文搞懂python threading(多线程)模块

    命令提示符如何打开并运行python文件链接 一. 1.active_count() , activeConut() 方法 功能 active_count() , activeConut() 返回处于 ...

最新文章

  1. python图片识别拉框_python目标检测给图画框,bbox画到图上并保存案例
  2. 《包青天》中的《鸳鸯蝴蝶梦》单元,剧中有一个很漂亮的女子叫“离垢”
  3. SmartNIC/DPU — 应用场景与功能特性
  4. Python+selenium 自动化 - 实现自动导入、上传外部文件实例演示
  5. Python编程基础:第五十六节 filter函数Filter
  6. python可变参数记录
  7. 数据结构与算法之母牛生牛
  8. mysql_connect报告“No such file or directory“错误的解决方法
  9. 设置qt的QChart曲线背景色透明
  10. 大气自适应会员中心帝国cms模板
  11. word横向网格线设置在哪里_word排版技巧:如何防止行距随字号而改变?
  12. 【STM32】STM32CubeMX教程二--基本使用(新建工程点亮LED灯)
  13. java captcha 验证码_java生成图片验证码的示例代码
  14. 系统开发视角下的诊断 ———— 动力系统(P)诊断故障10
  15. 共模电感的工作原理及选型
  16. recon-ng V5.0 更新版本 被动信息收集
  17. hdmi怎么支持2k分辨率_选择2K显示器有没有必要?
  18. win10的C盘满了清理方法
  19. 《狂人日记》(书感)
  20. NovAtel 板卡OEM617D配置步骤记录

热门文章

  1. css-模态对话框的制作
  2. 使用supervisor使Laravel的queue保持后台常驻
  3. 修改kubelet启动参数
  4. mysql之 slow log 慢查询日志
  5. 实实在在做一位教书匠(来自网络)
  6. 工厂方法模式--简单试例
  7. Android Ubuntu 安装问题FAQ
  8. 1.4.2.4. SAVING(Core Data 应用程序实践指南)
  9. ISAKMP:(1006):deleting node 1202729771 error TRUE reason Delete Larval
  10. App 留客率出炉:iPhone 大胜 Android!