python之路---装饰器函数
阅读目录
- 楔子
- 装饰器的形成过程
- 开放封闭原则
- 谈装饰器主要功能和装饰器固定结构
- 带参数的装饰器
- 多个装饰器装饰一个函数
楔子
作为一个会写函数的python开发,我们从今天开始要去公司上班了。写了一个函数,就交给其他开发用了。
def func1():print('in func1')
季度末,公司的领导要给大家发绩效奖金了,就提议对这段日子所有人开发的成果进行审核,审核的标准是什么呢?就是统计每个函数的执行时间。
这个时候你要怎么做呀?
你一想,这好办,把函数一改:
import time def func1():start = time.time()print('in func1')print(time.time() - start)func1()
来公司半年,写了2000+函数,挨个改一遍,1个礼拜过去了,等领导审核完,再挨个给删了。。。又1个礼拜过去了。。。这是不是很闹心?
你觉得不行,不能让自己费劲儿,告诉所有开发,现在你们都在自己原本的代码上加上一句计算时间的语句?
import time def func1():print('in func1')start = time.time() func1() print(time.time() - start)
还是不行,因为这样对于开发同事来讲实在是太麻烦了。
那怎么办呢?你灵机一动,写了一个timer函数。。。
import time def timer(func):start = time.time()func()print(time.time() - start)def func1():print('in func1')def func2():print('in func2')timer(func1) timer(func2)
这样看起来是不是简单多啦?不管我们写了多少个函数都可以调用这个计时函数来计算函数的执行时间了。。。尽管现在修改成本已经变得很小很小了,但是对于同事来说还是改变了这个函数的调用方式,假如某同事因为相信你,在他的代码里用你的方法用了2w多次,那他修改完代码你们友谊的小船也就彻底地翻了。
你要做的就是,让你的同事依然调用func1,但是能实现调用timer方法的效果。
import time def timer(func):start = time.time()func()print(time.time() - start)def func1():print('in func1')func1 =timer #要是能这样的就完美了。。。可惜报错 func1()
非常可惜,上面这段代码是会报错的,因为timer方法需要传递一个func参数,我们不能在赋值的时候传参,因为只要执行func1 = timer(func1),timer方法就直接执行了,下面的那句func1根本就没有意义。到这里,我们的思路好像陷入了僵局。。。
装饰器的形成过程
import timedef func1():print('in func1')def timer(func):def inner():start = time.time()func()print(time.time() - start)return innerfunc1 = timer(func1) func1()
装饰器——简单版1
忙活了这么半天,终于初具规模了!现在已经基本上完美了,唯一碍眼的那句话就是还要在做一次赋值调用。。。
你觉得碍眼,python的开发者也觉得碍眼,所以就为我们提供了一句语法糖来解决这个问题!
import time def timer(func):def inner():start = time.time()func()print(time.time() - start)return inner@timer #==> func1 = timer(func1) def func1():print('in func1')func1()
装饰器——语法糖
到这里,我们可以简单的总结一下:
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
还有最后一个问题要解决,刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?
def timer(func):def inner(a):start = time.time()func(a)print(time.time() - start)return inner@timer def func1(a):print(a)func1(1)
装饰器——带参数的装饰器
其实装饰带参的函数并不是什么难事,但假如你有两个函数,需要传递的参数不一样呢?
import time def timer(func):def inner(*args,**kwargs):start = time.time()re = func(*args,**kwargs)print(time.time() - start)return rereturn inner@timer #==> func1 = timer(func1) def func1(a,b):print('in func1')@timer #==> func2 = timer(func2) def func2(a):print('in func2 and get a:%s'%(a))return 'fun2 over'func1('aaaaaa','bbbbbb') print(func2('aaaaaa'))
装饰器——成功hold住所有函数传参
现在参数的问题已经完美的解决了,可是如果你的函数是有返回值的呢?
import time def timer(func):def inner(*args,**kwargs):start = time.time()re = func(*args,**kwargs)print(time.time() - start)return rereturn inner@timer #==> func2 = timer(func2) def func2(a):print('in func2 and get a:%s'%(a))return 'fun2 over'func2('aaaaaa') print(func2('aaaaaa'))
装饰器——带返回值的装饰器
刚刚那个装饰器已经非常完美了,但是正常我们情况下查看函数的一些信息的方法在此处都会失效
def index():'''这是一个主页信息'''print('from index')print(index.__doc__) #查看函数注释的方法 print(index.__name__) #查看函数名的方法
查看函数信息的一些方法
为了不让他们失效,我们还要在装饰器上加上一点来完善它:
from functools import wrapsdef deco(func):@wraps(func) #加在最内层函数正上方def wrapper(*args,**kwargs):return func(*args,**kwargs)return wrapper@deco def index():'''哈哈哈哈'''print('from index')print(index.__doc__) print(index.__name__)
装饰器——wraps demo
开放封闭原则
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
装饰器的主要功能和装饰器的固定结构
装饰器的主要功能:
在不改变函数调用方式的基础上在函数的前、后添加功能。
装饰器的固定格式:
def timer(func):def inner(*args,**kwargs):'''执行函数之前要做的'''re = func(*args,**kwargs)'''执行函数之后要做的'''return rereturn inner
装饰器的固定格式
from functools import wrapsdef deco(func):@wraps(func) #加在最内层函数正上方def wrapper(*args,**kwargs):return func(*args,**kwargs)return wrapper
装饰器的固定格式——wraps版
带参数的装饰器
假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?
一个一个的取消掉? 没日没夜忙活3天。。。
过两天你领导想通了,再让你加上。。。
def outer(flag):def timer(func):def inner(*args,**kwargs):if flag:print('''执行函数之前要做的''')re = func(*args,**kwargs)if flag:print('''执行函数之后要做的''')return rereturn innerreturn timer@outer(False) def func():print(111)func()
带参数的装饰器
多个装饰器装饰同一个函数
有些时候,我们也会用到多个装饰器装饰同一个函数的情况。
def wrapper1(func):def inner():print('wrapper1 ,before func')func()print('wrapper1 ,after func')return innerdef wrapper2(func):def inner():print('wrapper2 ,before func')func()print('wrapper2 ,after func')return inner@wrapper2 @wrapper1 def f():print('in f')f()
多个装饰器装饰同一个函数
转载于:https://www.cnblogs.com/FWF1944/p/10896637.html
python之路---装饰器函数相关推荐
- python装饰器函数-python之路——装饰器函数
阅读目录 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班了.写了一个函数,就交给其他开发用了. deffunc1():print('in func1') 季度末,公司的领导要给大 ...
- python带参数装饰器 函数名_python 全栈开发,Day11(函数名应用,闭包,装饰器初识,带参数以及带返回值的装饰器)...
一.函数名应用 函数名是什么?函数名是函数的名字,本质:变量,特殊的变量. 函数名(),执行此函数. python 规范写法 1. #后面加一个空格,再写内容,就没有波浪线了. 2.一行代码写完,下面 ...
- python中wraps_python装饰器函数wraps
python的装饰器是python的重要特性之一,通过装饰器你能够在执行已有的操作的同时,去执行额外的操作.装饰器的主要作用在不改变原有函数或者类等内部的实现的前提下,对其进行功能的拓展.这是装饰器最 ...
- python装饰器函数-Python精进-装饰器与函数对象
本文为<爬着学Python>系列第四篇文章. 从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新. 在Python的学习与运用中,我们迟早会遇到装饰器,这个概念对于初识装饰器的新手来说 ...
- python装饰器函数-python函数装饰器
什么是装饰器 装饰器是一个可调用的对象,其参数是另一个函数(被装饰的函数).装饰器可能会: 1,处理被装饰的函数,然后把它返回 2,将其替换成另一个函数或者对象 若有个名为decorate的装饰器,则 ...
- python装饰器函数-【python3】 函数 装饰器
第一步 : 了解装饰器 装饰器模式,重点在于装饰,装饰的核心仍是被装饰的对象. 举一个栗子:我今天穿了一件短袖,但是突然一阵风,短袖没办法为我御寒,我想到的办法是将短袖变得更厚更长,但是改造之后,它就 ...
- python装饰器函数-python装饰器1:函数装饰器详解
先混个眼熟 谁可以作为装饰器(可以将谁编写成装饰器): 函数 方法 实现了__call__的可调用类 装饰器可以去装饰谁(谁可以被装饰): 函数 方法 类 基础:函数装饰器的表现方式 假如你已经定义了 ...
- python装饰器函数-python函数装饰器之带参数的函数和带参数的装饰器用法示例
本文实例讲述了python函数装饰器之带参数的函数和带参数的装饰器用法.分享给大家供大家参考,具体如下: 1. 函数带多个参数 # 普通的装饰器, 打印函数的运行时间 def decrator(fun ...
- python装饰器函数后执行_Python装饰器限制函数运行时间超时则退出执行
实际项目中会涉及到需要对有些函数的响应时间做一些限制,如果超时就退出函数的执行,停止等待. 可以利用python中的装饰器实现对函数执行时间的控制. python装饰器简单来说可以在不改变某个函数内部 ...
最新文章
- 大厂程序员回乡真风光?敲锣打鼓游街欢迎,横幅写着月薪和公司!
- android androidx版本,Android AndroidX 简介与迁移
- 获得MFC窗口其它类指针的方法
- PHP从零开始--字段修饰符数据操作SQL语言
- 图像基本处理算法的简单实现(二)
- CDH5 6 7安装包
- 国内 RISC-V 产学研基地成立,Intel、Arm、RISC-V 将三分天下?
- 服务器重置密码后无法启动不了怎么办,Windows Server 2008 R2 忘记密码的处理方法...
- 学习Altas 笔记[js调用重载的方法出错,如何处理]
- EasyUI扩展方法
- 软件测试 集成测试
- Win10一键更换系统字体
- ftp客户端安装,六款可以安装的ftp客户端
- matlab读取数据流,【OpenBCI】(1):Matlab实时读取数据流(labstreaminglayer)
- js后代选择器_后代选择器和子元素选择器的区别
- node.js 基础
- uos软件打包注意事项
- 查看linux版本的命令
- 计算机电脑网络电缆,笔记本电脑的网络电缆在哪里
- 苏宁java二面,苏宁二面面试