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 == '':
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 == '':
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全栈开发-Day10 装饰器(闭合函数的应用场)的更多相关文章
- Python全栈开发之---装饰器
1.装饰器的形成过程 import time def func1(): print('in func1') def timer(func): def inner(): start = time.tim ...
- Python全栈开发:装饰器实例
#!/usr/bin/env python # -*- coding;utf-8 -*- """ 1.将outer函数放入内存 2.遇见@ + 函数名,则将该函数转换为装 ...
- python全栈开发_day12_装饰器
一:装饰器 1)什么是装饰器 装饰器的本质就是利用闭包,在满足开放(修改函数锁包含的功能)封闭(不改变源代码)的情况下完成操作. 2)装饰器的基本运用 def name_judge(f): def a ...
- python 全栈开发,Day113(方法和函数的区别,yield,反射)
一.方法和函数的区别 面向对象 初级 class StarkConfig(object): def __init__(self,model_class): self.model_class = mod ...
- Python全栈工程师(装饰器、模块)
ParisGabriel 每天坚持手写 一天一篇 决定坚持几年 全栈工程师 Python人工智能从入门到精通 装饰器 decorators(专业提高篇) 装饰 ...
- python全栈开发day13-迭代器、生成器、列表推导式等
昨日内容:函数的有用信息.带参数的装饰器.多个装饰器修饰一个函数 迭代器 可迭代对象:内部含有__iter__方法 迭代器 定义:可迭代对象.__iter__()就是迭代器,含有__iter__且__ ...
- Python全栈day20(装饰器基本理论)
一,什么是装饰器 装饰器:本质就是函数,功能是为其他函数添加附加功能 原则 1,不修改被修饰函数的源代码 2,不修改被修饰函数的调用方式 举例说明:有一个求和函数要求就算出函数的运行时间 正常代码应该 ...
- python全栈开发day10
day10知识点总结 while循环补充: continue,终止当前循环,开始下一次循环 break,终止所有循环 pycharm 技巧1.setting 中搜索 mouse 设置鼠标滚轮 改变字体 ...
- python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)
昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...
随机推荐
- 使用jsoup抓取新闻信息
1,jsoup简介 jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和 ...
- java.lang.IllegalArgumentException: Document base E:\Eclipse\workspace\.metadata\.plugins\org.eclips
1.错误描述 四月 13, 2015 5:56:55 下午 org.apache.catalina.core.AprLifecycleListener init 信息: The APR based A ...
- 芝麻HTTP:
只要你的Scrapy Field字段名字和 数据库字段的名字 一样.那么恭喜你你就可以拷贝这段SQL拼接脚本.进行MySQL入库处理. 具体拼接代码如下: def process_item(self, ...
- Django学习-15-Cookie
Cookie 1.如果没有cookie,那么所有的网站都不能登录 2.客户端浏览器上的文件,keyvalues形式存储的,类似字典 ...
- Entity Framework 乐观并发处理
Entity Framework 乐观并发处理 有一段时间没有更新博客了,今天终于有一些时间,和大家讨论一个Entity Framework 乐观并发处理的问题.首先需要说明的是,这里提到的 “并发” ...
- 【HAOI2015】树上操作(树链剖分)
题面 Description 有一棵点数为N的树,以点1为根,且树点有边权.然后有M个操作,分为三种: 操作1:把某个节点x的点权增加a. 操作2:把某个节点x为根的子树中所有点的点权都增加a. 操作 ...
- [ZJOI2007]时态同步
题目描述 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两个节点 ...
- [BZOJ2654] tree (kruskal & 二分答案)
Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色 ...
- wpf 研究之道 winform or wpf,u choose who?
很久以前,我们用winform做过一个五子棋的程序,当时用winform的画图,先画出棋盘...后来项目的研究阶段,偶尔用winform做个小工具.闲暇之余,看到介绍wpf的资料,只知道它采用了xam ...
- Postman使用小技巧
Postman使用小技巧 2017-09-13 目录: 1 自动生成流水号2 保存响应结果 1 自动生成流水号 返回 为了让接口具有幂等性,在设计时,往往有一个字段是唯一的(比如流水号,交易编号等), ...