Py装饰器
装饰器:
1.定义,什么是装饰器
装饰器本质是一个函数,它是为了给其他函数添加附加功能
2.装饰器的两个原则
原则1 不修改被修饰函数的源代码
原则2 不修改被修饰函数的调用方式
3.首先来看一个统计运行时间的程序
import time
def cal(l):
start_time=time.time()
res=0
for i in l:
time.sleep(0.02)
res=i+res
stop_time=time.time()
print('函数的运行时间是%s' %(stop_time-start_time))
cal(range(0,100))
4.但是有可能其他函数还有很多,如果在执行其他的程序的时候也想计算一下
运行时间,就要每次重新写上这个,十分麻烦,所以需要装饰器
装饰器=高阶函数+函数嵌套+闭包
函数嵌套定义:def里面再def一个
高阶函数定义:函数接收的参数是一个函数名或者函数返回值是一个函数名
闭包的定义:包就是变量,闭包就是封装变量。里面的变量名找不到时就往外层找
import time
def shit():
time.sleep(3)
print('you are eating shit')
#以下是装饰器函数测量函数的运行时间
def timmer(func):
print(func)
start_time=time.time()
func()
stop_time=time.time()
print('函数的运行时间是',(stop_time-start_time))
#主程序,调用方式
timmer(shit)
#并不修改原函数
shit()
import time
def shit(): #原始函数
time.sleep(3)
print('you are eating shit')
#以下是装饰器函数测量函数的运行时间
def timmer(func):
def wrapper():
start_time=time.time()
func()
stop_time=time.time()
print('运行时间为',stop_time-start_time)
return wrapper
#主程序
res = timmer(shit) #由于返回值是wrapper的地址,所以res是wrapper地址
res() #执行wrapper函数
shit() #可以看见并不影响原函数
5.注意@timemer相当于 shit= timmer(shit)
先把timmer执行了,然后获得的是wrapper的内存地址,然后把shit给wrapper
执行了之后再
因此以下要加上装饰器的时候只需要在想加装饰器的函数的前面加上@timmer
示例
#以下是装饰器函数测量函数的运行时间
import time
def timmer(func):
def wrapper():
start_time=time.time()
func()
stop_time=time.time()
print('运行时间为',stop_time-start_time)
return wrapper
@timmer
def shit(): #原始函数
time.sleep(3)
print('you are eating shit')
return '是返回值'
shit() #加上@timmer之后,直接调用就可以了
但是这个程序存在一个小问题,就是执行加装装饰器之后得不到shit函数里面的
返回值
6.针对上一个程序里面的问题,优化后的方法
#以下是装饰器函数测量函数的运行时间
import time
def timmer(func):
def wrapper():
start_time=time.time()
res=func()
stop_time=time.time()
print('运行时间为',stop_time-start_time)
return res
return wrapper
@timmer
def shit(): #原始函数
time.sleep(3)
print('you are eating shit')
return '是返回值'
shit() #加上@timmer之后,直接调用就可以了
但是这个程序还是有小问题,就是如果要修饰的函数里不止一个参数
比如shit函数变成def shit(ab,cd),那就会运行出错
7.由于不同的函数可能有不同个数的参数,可以进行以下的形式的修改
#以下是装饰器函数测量函数的运行时间
import time
def timmer(func):
def wrapper(*args,**kargs):
start_time=time.time()
res=func(*args,**kargs)
stop_time=time.time()
print('运行时间为',stop_time-start_time)
return res
return wrapper
@timmer
def shit(name,age,dap): #原始函数
time.sleep(3)
print('you are eating shit')
return '是返回值'
res=shit('aa',12,56)
解压序列:
如果想从很大的一条列表中抽出头和尾,除了使用[]的方式抽,还可以
使用解压的方式
l1=[23,45,8,4,5,8,4,53,82,254,'as']
a,b,*_,d=l1 #这句话解压把整个列表分成了几部分
print(a) #a是23
print(d) #d是as
print(b) #b是45
print(_) #_是除去abd剩下的那些部分
验证功能装饰器
def auth_func(func):
def wrapper(*args, **kwargs):
username = input('用户名')
password = input('密码')
if username == 'sb' and password == '123':
res=func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
return wrapper
@auth_func
def index():
print('欢迎来到主页')
@auth_func
def home():
print('欢迎回家 ')
index()
home()
时还需要重新输入用户名和密码
改良:加入登录状态的判别
user_dic={'login':False}
def auth_func(func):
def wrapper(*args, **kwargs):
if user_dic['login']==1:
res=func(*args, **kwargs)
return res
username = input('用户名')
password = input('密码')
if username == 'sb' and password == '123':
user_dic['login']=1
res=func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
return wrapper
@auth_func
def index():
print('欢迎来到主页')
@auth_func
def home():
print('欢迎回家 ')
index()
home()
user_dic={'login':False}
def aurhorlog(authortype=0): #外面可以嵌套多一层,这样可以指定传多点参数
def auth_func(func): #上面那层有authortype,因此下面可以直接操作这参数
def wrapper(*args, **kwargs):
if user_dic['login']==1:
res=func(*args, **kwargs)
return res
username = input('用户名')
password = input('密码')
if username == 'sb' and password == '123':
user_dic['login']=1
res=func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
return wrapper
return auth_func
#@aurhorlog()是语法糖,它相当于下面的几句话
# auth_func = aurhorlog(authortype=1)
# wrapper = auth_func(index)
# index=wrapper()
@aurhorlog()
def index():
print('欢迎来到主页')
@aurhorlog()
def home():
print('欢迎回家 ')
index()
home()
重点:装饰器格式
#装饰器总共是三层
def fun(ptcanshu1=1): #第一层的里面可以弄一个普通参数
def fun1(func): #第二层里是func,它代表着准备要被装饰的函数
def wrapper(): #第三层里不放参数
print('hello')
func() #此处为调用要被装饰的函数
return wrapper
return fun1
@fun()
def shit():
print('shit')
shit()
def pt1(ptcanshu2=1):
def pt2(ptcanshu3=3):
def fun(ptcanshu1=1): #第一层的里面可以弄一个普通参数
def fun1(func): #第二层里是func,它代表着准备要被装饰的函数
def wrapper(): #第三层里不放参数
print('hello')
func() # 此处为调用要被装饰的函数
return wrapper
return fun1
return fun()
return pt2()
@pt1()
def shit():
print('shit')
#如果要装饰函数就需要取到最内层的wrapper
shit()
Py装饰器的更多相关文章
- py装饰器,生成器,迭代器
emmmmm....看了好久才能大概的看懂一点关于装饰器的内容...import sys # 引入sys模块import timeimport functoolsfrom functools impo ...
- Python基础2:反射、装饰器、JSON,接口
一.反射 最近接触到python的反射机制,遂记录下来已巩固.但是,笔者也是粗略的使用了__import__, getattr()函数而已.目前,笔者的理解是,反射可以使用户通过自定义输入来导入响应的 ...
- python使用装饰器@函数式化django开发
django是一个python web开发的框架.作为一个框架MVC的架构已经实现起来了.但是编码的时候你经常要进行进一步的抽象. AOP是一种称为面向切面的开发思想,意思是将部分功能代码在运行时动态 ...
- Django(五)母版继承、Cookie、视图装饰器等
大纲 一.内容回顾 补充:默认值 补充:命名空间 二.模板语言 1.母版继承 2.include 3.自定义simple_tag 三.Cookie Cookie 使用总结 四.视图 1.获取用户请求相 ...
- selenium 中装饰器作用
前面讲到unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量,但是有个弊端,比如打开浏览器操作,每次执行用例时候都会重新打开,这样就会浪费很多时间.于是就想是不是可以只打开一 ...
- 就谈个py 的装饰器 decorator
很早很早就知道有这么个 装饰器的东西,叫的非常神秘. 包括c# 和 java 中都有这个东西, c#中叫做attribut 特性,java中叫做Annotation 注解,在偷偷学习c#教程的时候, ...
- py基础4--迭代器、装饰器、软件开发规范
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1. 列表生成式,迭代器&生成器 列表生成式 我现在有个需求, ...
- Py修行路 python基础 (十)装饰器
装饰器 一.定义 装饰器:顾名思义,就是对某个东西起到装饰修饰的功能. python中的装饰器,其本质上就是一个python函数,它可以让其他函数在不需要任何代码变动的前提下增加额外功能.通俗理解就是 ...
- [原创]django+ldap实现单点登录(装饰器和缓存)
前言 参考本系列之前的文章,我们已经搭建了ldap并且可以通过django来操作ldap了,剩下的就是下游系统的接入了,现在的应用场景,我是分了2个层次,第一层次是统一认证,保证各个系统通过ldap来 ...
随机推荐
- C#中的深度学习(二):预处理识别硬币的数据集
在文章中,我们将对输入到机器学习模型中的数据集进行预处理. 这里我们将对一个硬币数据集进行预处理,以便以后在监督学习模型中进行训练.在机器学习中预处理数据集通常涉及以下任务: 清理数据--通过对周围数 ...
- Python进阶——什么是描述符?
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 在 Python 开发中,你可能听说过「描述符」这个概念,由于我们很少直接使用它,所以大部分开发人员 ...
- 走进 Python 类的内部
这篇文章和大家一起聊一聊 Python 3.8 中类和对象背后的一些概念和实现原理,主要尝试解释 Python 类和对象属性的存储,函数和方法,描述器,对象内存占用的优化支持,以及继承与属性查找等相关 ...
- 关于MVC中 服务器无法在发送 HTTP 标头之后修改 cookie此类问题的解决
处理方法 使用过滤器控制权限时,若无权则跳转到无权页面,但是每次跳转都会出现 ERROR - System.Web.HttpException (0x80004005): 服务器无法在已发送 HTTP ...
- 【进程/作业管理】篇章四:Linux任务计划、周期性任务执行
命令归纳: at 未来时间点让特定任务运行一次 batch 未来时间点让系统自行选择在系统资源较空闲的时间去执行指定的任务 corn 周期性任务计划(corntad) at命令详解 <--- 假 ...
- Winform Dock顺序调整
在布局的时候,当一个窗体内有多个控件使用了Dock属性来布局,Dock顺序的调整: 最近被.net winform中的控件布局搞困惑了,由于控件都是使用Dock方式的,操作起来也是比较方便,如果最大化 ...
- (一)必须掌握的linux命令行快捷键
1.序 使用linux时,接触最多的莫过于命令行,参差不齐,形形色色,对于短的命令行使用脑残的上下左右,back,del就够用了:而对于带有很多参数的长的命令行,再使用上下左右,del,back显得那 ...
- ReentrantLock锁-CAS与阻塞
ReentrantLock锁 ReentrantLock通过原子操作和阻塞实现锁原理,一般使用lock获取锁,unlock释放锁 lock的时候可能被其他线程获得所,那么此线程会阻塞自己,关键原理底层 ...
- Plugin 插件体系
Solon 的插件也可以叫扩展组件,相当于Spring 的 starter.Solon已经提供了大量的基础插件,但对第三方的框架适配目前较少. 插件 说明 boot插件:: 说明 org.noear: ...
- 发起一个开源项目:基于 .NET 的博客引擎 fluss
今天我们发起一个开源项目,它的名字叫 fluss,fluss 是 river 的德语. 百川归海,每一个博客就如一条河流,输入的是文字,流出的是知识,汇入的是知识的汪洋大海. 川流不息,fluss 是 ...