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大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
随机推荐
- linux c语言 select函数用法
linux c语言 select函数用法 表头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<unis ...
- solaris启动过程详解
在Sparc平台下,Solaris系统中有一个类似PC BIOS的芯片程序(EEPROM OpenBoot)负责识别分区.文 件系统和加载内核,在Solaris 2.6之后的版本中,默认的内核文件存放 ...
- java.lang.NoClassDefFoundError:org/hamcrest/SelfDescribing
1.错误描述 java.lang.NoClassDefFoundError:org/hamcrest/SelfDescribing 2.错误原因 将junit-4.11.jar导入到lib目录中,出现 ...
- Vue 非父子组件通信方案
Vue 非父子组件通信方案 概述 在 Vue 中模块间的通信很普遍 如果是单纯的父子组件间传递信息,父组件可以使用 props 将数据向下传递到子组件,而在子组件中可以使用 events (父组件需要 ...
- webpack学习(一):webpack 介绍&安装&常用命令
一.简单介绍 什么是Webpack Webpack是一款用户打包前端模块的工具,它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源. 主要是用来打包在浏览器端使用的ja ...
- HTTP的长连接,你不知道的连接。。。
长连接起源 什么样的连接才能称之为长连接?要多长.... http是一种无状态的协议,也就是stateless协议,而http协议又是建立在tcp/ip协议的基础之上的. 无状态表示每次请求都是一次独 ...
- 初学 Java Web 开发,从 Servlet 开发
1. 基本要求:Java 编程基础 有良好的 Java 语言编程基础,这是必须的,在讨论 Web 开发技术时提了一个 Java 编程基础的问题会被鄙视的. 2. 环境准备 (Eclipse + Tom ...
- luogu【P3377】 【模板】左偏树
左偏树 顾名思义 向左偏的树 (原题入口) 它有啥子用呢??? 当然是进行堆的合并啦2333普通堆的合并其实是有点慢的(用优先队列的话 只能 一个pop 一个push 来操作 复杂度就是O(n log ...
- 【BZOJ4736】温暖会指引我们前行(Link-Cut Tree)
[BZOJ4736]温暖会指引我们前行(Link-Cut Tree) ##题面 神TM题面是UOJ的 题解 LCT傻逼维护最大生成树 不会的可以去做一做魔法森林 #include<iostrea ...
- Js - JQ事件委托( 适用于给动态生成的脚本元素添加事件)
最近一段时间打了一个大仗,现在总算消停点,才有时间来做个总结吧算是: 移动端遇到一个项目,是一个列表的侧滑栏,在我这里用jq写的交互事件.自测各方面都挺好的,美滋滋的给了研发.研发也美滋滋的开始开发. ...