一、什么是装饰器

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

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

合到一起就是:

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

二、为什么要有装饰器

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

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

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

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

三、无参装饰器的使用

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

def index(x,y):
print(x,y)
return 123
res = index(1,2)
print(res)
>>>1,2
>>>123

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

import time
start = time.time()
def index(x,y):
print(x,y)
return 123
stop = time.time()
print(stop - start)
res = index(1,2)
print(res)
>>>0.0007340908050537
>>>1,2
>>>123

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

import time
def index(x, y):
print(x, y)
return 123
def outter(*args,**kwargs):
start = time.time()
res = index(*args,*kwargs)
stop = time.time()
print(stop - start)
return res
res = outter(1,2)
print(res)
>>>1,2
>>>0.0007340908050537
>>>123

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

import time
def index(x,y):
print(f"index{x},{y}")
return 123 def name(your_name):
print(f"your name:{your_name}")
return 456 def timmer(func):
def outter(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print(stop - start)
return res
return outter
index = timmer(index)
res = index(1,2)
print(res) >>>1,2
>>>0.0007340908050537
>>>123 name = timmer(name)
res = name("hz")
print(res) >>>your name:hz
>>>0.0008175373077393
>>>456

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

import time

def timmer(func):
def outter(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print(stop - start)
return res
return outter
#如果此处有多个装饰器,按照从下到上的顺序装饰
@timmer
#@timmer相当于 index=timmer(index)
def index(x,y):
print(f"index{x},{y}")
return 123 @timmer
#@timmer相当于 name=timmer(name)
def name(your_name):
print(f"your name:{your_name}")
time.sleep(1)
return 456 res = index(1,2)
print(res) >>>1,2
>>>0.0007340908050537
>>>123 res = name("hz")
print(res) >>>your name:hz
>>>0.0008175373077393
>>>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. gradle的搭建和配置

    下载 官方网站:https://gradle.org/install/#manually 提供了两种下载方式,Binary-only是只下载二进制源码,Complete, with docs and ...

  2. 解决错误【selenium.common.exceptions.SessionNotCreatedException】

    以前能用,突然不能用了,是浏览器版本可能升级了,与原来的weddriver驱动版本不符合 解决办法:1.更新浏览器驱动, 2.降低浏览器版本

  3. node实现文件属性批量修改(时间属性)

    前言 在默认情况下,一个文件的创建时间和修改时间是系统自己设定的,我们不能修改该的.但我们有时为了某种特殊需要,为了不让别人一眼看出文件已经给修改了,我们又需要修改文件的创建时间和修改时间.那么如何修 ...

  4. CODING DevOps 系列第四课:DevOps 中的质量内建实践

    什么是质量内建 随着时间的推移,我们项目的开发效率会逐渐降低,直到几年之后整个项目可能就无法维护,只能推倒重来.具体的表现首先就是随着时间推移,我们会发现整个需求列表里面能做的需求越来越少,因为每当我 ...

  5. C/S C# WPF锐浪报表教程

    前言:锐浪报表是一种中国式报表的报表开发工具.博主使用锐浪报表有一段时间了,积累了一些经验希望能帮助你快速掌握并使用 第一章:集成项目 首先我们先去锐浪报表官网下载并安装锐浪报表. 创建WPF应用程序 ...

  6. 【Java思考】Java 中的实参与形参之间的传递到底是值传递还是引用传递呢?

    科普: 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数. 引用传递(pass by reference)是指在 ...

  7. 深入浅出PyTorch(算子篇)

    Tensor 自从张量(Tensor)计算这个概念出现后,神经网络的算法就可以看作是一系列的张量计算.所谓的张量,它原本是个数学概念,表示各种向量或者数值之间的关系.PyTorch的张量(torch. ...

  8. 深入浅出Transformer

    Transformer Transformer是NLP的颠覆者,它创造性地用非序列模型来处理序列化的数据,而且还获得了大成功.更重要的是,NLP真的可以"深度"学习了,各种基于tr ...

  9. SSL/TSL 原理( 握手原理和传输原理)

    本文参考<计算机网络 自顶向下方法> 目录 背景 通信的4要素 SSL/TLS in Detail 通讯保证 The Handshake Protocol 1. Initial Clien ...

  10. 【Spring】AOP的代理默认是Jdk还是Cglib?

    菜瓜:你觉得AOP是啥 水稻:我觉得吧,AOP是对OOP的补充.通常情况下,OOP代码专注功能的实现,所谓面向切面编程,大多数时候是对某一类对象的方法或者功能进行增强或者抽象 菜瓜:我看你这个理解就挺 ...