一、什么是装饰器

装饰:是对其他已有的事物添加额外具有一定意义的事物

器:是一种工具,在程序内可以定义成函数

合到一起就是:

​ 装饰器就是一个函数,为了给其他函数添加额外的功能

二、为什么要有装饰器

这里要引入一个设计程序的一个概念:开放封闭原则

开放:指的是对扩展功能是开放的,就是指原来设计的功能是可装饰的

封闭:指的是对修改源代码是封闭的,原来代码的某一个功能可能在不同场景有多种不同的应用,一旦修改会造成连锁反应。为此,一般情况下上线的功能不做源代码的修改

装饰器就是在不修改被装饰对象的

三、无参装饰器的使用

需求:不修改index函数的源代码,以及调用方式的前提下加统计函数运行时间的功能

  1. def index(x,y):
  2. print(x,y)
  3. return 123
  4. res = index(1,2)
  5. print(res)
  6. >>>1,2
  7. >>>123

第一步:我们先要回忆函数的开放封闭原则,不能对函数源代码修改,我们只能在函数外修改

  1. import time
  2. start = time.time()
  3. def index(x,y):
  4. print(x,y)
  5. return 123
  6. stop = time.time()
  7. print(stop - start)
  8. res = index(1,2)
  9. print(res)
  10. >>>0.0007340908050537
  11. >>>1,2
  12. >>>123

第二步:这里我们已经实现了不修改index源码也不修改参数调用方式的情况下添加新功能了但是这样写的局限性很高,我们只对当前位置的函数index进行了装饰,当然在整个程序里index不可能只调用一次,如果对每个地方都修改就很麻烦。所以我们应该想到,把装饰器写成函数

  1. import time
  2. def index(x, y):
  3. print(x, y)
  4. return 123
  5. def outter(*args,**kwargs):
  6. start = time.time()
  7. res = index(*args,*kwargs)
  8. stop = time.time()
  9. print(stop - start)
  10. return res
  11. res = outter(1,2)
  12. print(res)
  13. >>>1,2
  14. >>>0.0007340908050537
  15. >>>123

第三步:这里我们看起来是节省了重复代码,可以直接用outter来当更新过的index,但是我们会发现我们这个outter被写死了,我们这个装饰器只能为index函数工作,这是不符合常理的,所以我们应该把它关于index的值作为变量重新传,但是我们outter的参数已经不能修改了必须是*,**,所以这里就用到了闭包函数的应用

  1. import time
  2. def index(x,y):
  3. print(f"index{x},{y}")
  4. return 123
  5. def name(your_name):
  6. print(f"your name:{your_name}")
  7. return 456
  8. def timmer(func):
  9. def outter(*args,**kwargs):
  10. start = time.time()
  11. res = func(*args,**kwargs)
  12. stop = time.time()
  13. print(stop - start)
  14. return res
  15. return outter
  16. index = timmer(index)
  17. res = index(1,2)
  18. print(res)
  19. >>>1,2
  20. >>>0.0007340908050537
  21. >>>123
  22. name = timmer(name)
  23. res = name("hz")
  24. print(res)
  25. >>>your name:hz
  26. >>>0.0008175373077393
  27. >>>456

最后一步:为了程序员编写程序的方便,引入了语法糖的概念,语法糖就是,在编译结果不便的情况下,让代码更加简洁优美。此处语法糖的应用项待遇代替了装饰器调用的代码

  1. import time
  2. def timmer(func):
  3. def outter(*args,**kwargs):
  4. start = time.time()
  5. res = func(*args,**kwargs)
  6. stop = time.time()
  7. print(stop - start)
  8. return res
  9. return outter
  10. #如果此处有多个装饰器,按照从下到上的顺序装饰
  11. @timmer
  12. #@timmer相当于 index=timmer(index)
  13. def index(x,y):
  14. print(f"index{x},{y}")
  15. return 123
  16. @timmer
  17. #@timmer相当于 name=timmer(name)
  18. def name(your_name):
  19. print(f"your name:{your_name}")
  20. time.sleep(1)
  21. return 456
  22. res = index(1,2)
  23. print(res)
  24. >>>1,2
  25. >>>0.0007340908050537
  26. >>>123
  27. res = name("hz")
  28. print(res)
  29. >>>your name:hz
  30. >>>0.0008175373077393
  31. >>>456

day17 装饰器(上)的更多相关文章

  1. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  2. python迭代器,生成器,装饰器,context模块

    迭代器iteration 是访问集合元素的一种方式,只能往前不能往后迭代器的特点:1,访问者不需要关注迭代器内部结构,只需通过next()不断取下一个内容2,访问不能回退3,循环较大数据集合时,省内存 ...

  3. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  4. Python入门笔记(19):Python函数(2):函数/方法装饰器

    一.装饰器(decorators) 装饰器的语法以@开头,接着是装饰器函数的名字.可选参数. 紧跟装饰器声明的是被装饰的函数和被装饰的函数的可选参数,如下: @decorator(dec_opt_ar ...

  5. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

  6. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  7. 从C#到TypeScript - 装饰器

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  8. Python装饰器的解包装(unwrap)

    在Python 3.4 中,新增一个方法unwrap,用于将被装饰的函数,逐层进行解包装. inspect.unwrap(func, *, stop=None) unwrap方法接受两个参数:func ...

  9. Python全栈开发之---装饰器

    1.装饰器的形成过程 import time def func1(): print('in func1') def timer(func): def inner(): start = time.tim ...

随机推荐

  1. 阿里巴巴二面凉经 flatten扁平化对象与数组

    2020-04-13 阿里巴巴二面凉经 flatten扁平化对象与数组 在线笔试的时候写错了一点点 太可惜了哎 还是基础不够扎实... const input = { a: 1, b: [ 1, 2, ...

  2. FWT,FST入门

    0.目录 目录 0.目录 1.什么是 FWT 2. FWT 怎么做 2.1. 或卷积 2.2.与卷积 2.3.异或卷积 2.4.例题 3. FST 3.1. FST 怎么做 3.2.例题 1.什么是 ...

  3. C#数据结构与算法系列(五):常见单链表笔试

    1.求单链表中有效节点个数 public static int GetLength(HeroNode headNode) { int length = ; var cur = headNode.Nex ...

  4. C# 9.0 新特性之目标类型推导 new 表达式

    阅读本文大概需要 2 分钟. 呼~~,每次过完一个周末,写作就失去了动力,一两天才能缓过来.尽管如此,还是要坚持写好每一篇文章的.宁缺毋滥嘛,宁愿发文的频率低一点,也要保证文章的质量,至少排版不能差, ...

  5. Linux MySQL集群搭建之主从复制

    前期准备 准备两台Linux,一主,一从,具体Linux安装MySQL操作步骤:点我直达 集群搭建 注意事项 一主可以多从 一从只能一主 关闭主从机器的防火墙策略 chkconfig iptables ...

  6. excel筛选重复项代码

    Sub test()'updateby Extendoffice 20151030    Dim xRng As Range    Dim xTxt As String    On Error Res ...

  7. c#openCV图片传递-尝试读取或写入受保护的内存。这通常指示其他内存已损坏。解决方法

    未处理AccessViolationException 这通常指示其他内存已损坏,这里内存损坏并非物理的内存条损坏.猜想是执行到此步骤后,内存空间被清理了,没有找到内存地址的感觉. public st ...

  8. 设计模式系列之组合模式(Composite Pattern)——树形结构的处理

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  9. 这篇文章,我们来谈一谈Spring中的属性注入

    本系列文章: 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configuration注解? 谈谈Spring中的对象跟Bean,你知道Spring怎么创 ...

  10. vue开发搭建(npm安装 + vue脚手架安装)

    一.概念 1.npm:  Nodejs下的包管理器. 2.webpack: 它主要的用途是通过CommonJS的语法,把所有浏览器端需要发布的静态资源,做相应的准备,比如资源的合并和打包. 3.vue ...