python开发装饰器的应用
python全栈开发-Day10 装饰器(闭合函数的应用场)
一、 装饰器
装饰器就是闭包函数的一种应用场景
什么是闭包函数?我们再来回忆一下:
闭包函数:
定义在函数内部的函数,并且该函数包含对外部函数作用域(强调:对全局作用域名字的引用不算闭包)名字的引用,该函数称为闭包函数
说到作用域我们再回忆下:
作用域:
全局范围:内置+全局
全局有效,全局存活
局部范围:局部
局部有效,局部存活
作用域关系是在函数定义阶段就规定死,与调用位置无关,
也就是说,无论函数在哪儿调用,都必须回到当初定义函数时的位置找作用域关系
一 、为何要用装饰器
#开放封闭原则: #软件一旦上线后,就应该遵循开放封闭原则,对修改源代码是封闭的,对功能的扩展是开放的,也就是我们必须找到一种解决方法: #能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能.
二 、什么是装饰器
#装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。 #强调装饰器的原则: #1 、不修改被装饰对象的源代码 #2 、不修改被装饰对象的调用方式 #装饰器的目标: #在遵循1和2的前提下,为被装饰对象添加上新功能
三 、装饰器的使用
#我们现在给下面函数增加一个运行时间的功能 import time def index(): time.sleep(3) print('welcome to index page') #修改一 def index(): start_time=time.time() time.sleep(3) print('welcome to index page') stop_time=time.time() print('run time is %s' %(stop_time-start_time)) index() #功能实现 #评语:直接改源代码,这么搞被开了。。。
#再来一位童靴,来实现功能 #修改二 import time def index(): time.sleep(1) print('welcome to index page') start_time=time.time() index() stop_time = time.time() print('run time is %s' % (stop_time - start_time)) #评语:有好多函数要实现这个功能,写N遍变这个代码, #后期维护一脸懵逼,还是被开。。。
#再来一位童靴,功能重复实现看我用强大的函数 #修订三: import time def index(): time.sleep(3) print('welcome to index page') def wrapper(func): #func=index start_time=time.time() func() #index() stop_time = time.time() print('run time is %s' % (stop_time - start_time)) wrapper(index) #评语:修改了原函数的调用方式,依然被开。。。
#终于来了位小牛的童靴,函数的值可以返回,然后我再把重新定义index #修订四: import time def index(): time.sleep(3) print('welcome to index page') def outter(func): #func=最原始的index # func=最原始的index def wrapper(): start_time=time.time() func() stop_time=time.time() print(stop_time-start_time) return wrapper index=outter(index) # 新的index=wrapper index() #wrapper() 功能基本实现 #评语:在原值没有返回值是没问题,但是有返回值的情况下,这么搞就会发现返回的是None
#这次小牛牛童靴路过看到这情况,say这么搞! #修订五 import time def index(): time.sleep(1) print('welcome to index page') return 123 #假使这里返回123 返回值可以是任意类型 #==============下面就是装饰器 def timmer(func): #func=最原始的index def wrapper(*args,**kwargs): #可变长参数 start_time=time.time() res=func(*args,**kwargs) #调用最原始的index stop_time=time.time() print(stop_time-start_time) return res #index()运行的返回值 return wrapper index=timmer(index) # 新的index=wrapper print(index()) #功能已经实现,返回值123 #评语:这里的装饰的功能已经实现,返回的值也得到,小牛牛不是白叫的
#天上五彩红光,大牛童靴出现!各位童靴火速围观! import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print(stop_time-start_time) return res return wrapper @timmer #index=timmer(index) 装饰器的标准格式! def index(): time.sleep(1) print('welcome to index page') return 123 @timmer # home=timmer(home) def home(name): time.sleep(2) print('welcome %s to home page' %name) # index() #home('egon') #评语:大牛就是大牛!大牛say:教你们绝技,不会的童靴可以照下面的模板实现: #无参装饰器模板 def outer(func): #outer,inner名字功能随意 def inner(*args,**kwargs): res=func(*args,**kwargs) return res return inner @outer #装饰器要在装饰函数的上方 def duoduo(): pass
四 、装饰器语法
#被装饰函数的正上方,单独一行 @deco1 @deco2 @deco3 def foo(): pass #foo=deco1(deco2(deco3(foo))) #这里的思想就是最上面装饰器,装饰的下面所有的函数(deco2,deco3,foo) #然后deco2装饰(deco3,foo),最后deco3装饰foo #功能的不同,放的顺序也要注意,不然装饰的效果可能实现的就不对了!
五、多个装饰器的使用:
import time current_user={ 'username':None, # 'login_time':None } def auth(func): # func=index def wrapper(*args,**kwargs): if current_user['username']: #这里是认证过的,下次就不用认证 print('已经登陆过了') res=func(*args,**kwargs) return res uname=input('用户名>>: ').strip() pwd=input('密码>>: ').strip() if uname == 'egon' and pwd == '123': print('登陆成功') current_user['username']=uname res=func(*args,**kwargs) return res else: print('用户名或密码错误') return wrapper def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print(stop_time-start_time) return res return wrapper @timmer # timmer 统计的是auth+index的执行时间 @auth #我们只装饰index的话就要把@timmer紧跟index def index(): time.sleep(1) print('welcome to index page') return 123 @auth @timmer #这里统计的就是home运行的时间 def home(name): time.sleep(2) print('welcome %s to home page' %name) #index() #home("duoduo")
六、有参数的装饰器的使用:
import time current_user={ 'username':None, # 'login_time':None } def auth(engine): #道理还是那个道理,在外面包了一层engine的值 # engine='file' #这个值外面穿什么进来就是什么 def auth2(func): # func=index def wrapper(*args,**kwargs): if engine == 'file': if current_user['username']: print('已经登陆过了') res=func(*args,**kwargs) return res uname=input('用户名>>: ').strip() pwd=input('密码>>: ').strip() if uname == 'egon' and pwd == '123': print('登陆成功') current_user['username']=uname res=func(*args,**kwargs) return res else: print('用户名或密码错误') elif engine == 'mysql': #engine 值得判断情况 print('基于MyQL的认证') elif engine == 'ldap': print('基于LDAP的认证') return wrapper return auth2 #这里也要返回auth2的内存地址 @auth('ldap') #@auth2 #index=auth2(index) #index=wrapper def index(): time.sleep(1) print('welcome to index page') return 123 index() # wrapper()
python开发装饰器的应用的更多相关文章
- 详解Python的装饰器
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
- 浅谈Django的中间件与Python的装饰器
浅谈Django的中间件 与Python的装饰器 一.原理 1.装饰器是Python的一种语法应用,利用闭包的原理去更改一个函数的功能,即让一个函数执行之前先到另外一个函数中执行其他需求语句,在执行该 ...
- 进阶Python:装饰器 全面详解
进阶Python:装饰器 前言 前段时间我发了一篇讲解Python调试工具PySnooper的文章,在那篇文章开始一部分我简单的介绍了一下装饰器,文章发出之后有几位同学说"终于了解装饰器的用 ...
- Python 之装饰器
Python 的装饰器可谓是提高开发效率的一大利器.然而初学装饰器的时候感觉很难理解,因为除了 Python 之外没听说哪个语言有这种东西. 而且网上看的很多解释看似容易理解,但只能很快理解了装饰器能 ...
- 我终于弄懂了Python的装饰器(一)
此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 一 ...
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- Python札记 -- 装饰器补充
本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...
- python基础——装饰器
python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
随机推荐
- C#之AES256位加密解密
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分 ...
- 用DataRelation给多个DataTable建立关系并显示到TreeView
DataRelation 对象执行两种功能: 它可使与正使用的记录相关的记录可用.如果在父记录 (GetChildRows) 中,则它提供子记录:如果正使用子记录 (GetParentRow),则它提 ...
- C# 时间格式化大全
DateTime dt = DateTime.Now; Label1.Text = dt.ToString();//2005-11-5 13:21:25 Label2.Text = dt ...
- freemarker中的split字符串分割(十六)
1.简易说明 split分割:用来根据另外一个字符串的出现将原字符串分割成字符串序列 2.举例说明 <#--freemarker中的split字符串分割--> <#list &quo ...
- 解决无法同步 OneNote 的问题
在本地创建的笔记本,无法共享到云端,显示无法连接onedrive. 关闭改笔记本,重新连接共享. 参考: https://support.office.com/zh-cn/article/%E8%A7 ...
- zk个人入门学习总结(1)
ZooKeeper是一种分布式协调服务,用于管理大型主机.在分布式环境中协调和管理服务是一个复杂的过程.ZooKeeper通过其简单的架构和API解决了这个问题.ZooKeeper允许开发人员专注于核 ...
- 【BZOJ2565】最长双回文串(回文树)
[BZOJ2565]最长双回文串(回文树) 题面 BZOJ 题解 枚举断点\(i\) 显然的,我们要求的就是以\(i\)结尾的最长回文后缀的长度 再加上以\(i+1\)开头的最长回文前缀的长度 至于最 ...
- 【POJ3207】Ikki's Story IV - Panda's Trick
POJ 3207 Ikki's Story IV - Panda's Trick liympanda, one of Ikki's friend, likes playing games with I ...
- HiHocoder1419 : 后缀数组四·重复旋律4&[SPOJ]REPEATS:Repeats
题面 Hihocoder Vjudge Sol 题目的提示说的也非常好 我对求\(LCP(P - L + len \% l, P + len \% L)\)做补充 \(len=LCP(P, P + L ...
- Java 多线程异步处理demo
java中实现多线程 1)继承Thread,重写里面的run方法 2)实现runnable接口通过源码发现:第一种方法说是继承Tread然后重写run方法,通过查看run方法的源码,发现run方法里面 ...