装饰器:

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()
小型示例2(以函数返回值是一个函数名来制作)

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装饰器的更多相关文章

  1. py装饰器,生成器,迭代器

    emmmmm....看了好久才能大概的看懂一点关于装饰器的内容...import sys # 引入sys模块import timeimport functoolsfrom functools impo ...

  2. Python基础2:反射、装饰器、JSON,接口

    一.反射 最近接触到python的反射机制,遂记录下来已巩固.但是,笔者也是粗略的使用了__import__, getattr()函数而已.目前,笔者的理解是,反射可以使用户通过自定义输入来导入响应的 ...

  3. python使用装饰器@函数式化django开发

    django是一个python web开发的框架.作为一个框架MVC的架构已经实现起来了.但是编码的时候你经常要进行进一步的抽象. AOP是一种称为面向切面的开发思想,意思是将部分功能代码在运行时动态 ...

  4. Django(五)母版继承、Cookie、视图装饰器等

    大纲 一.内容回顾 补充:默认值 补充:命名空间 二.模板语言 1.母版继承 2.include 3.自定义simple_tag 三.Cookie Cookie 使用总结 四.视图 1.获取用户请求相 ...

  5. selenium 中装饰器作用

    前面讲到unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量,但是有个弊端,比如打开浏览器操作,每次执行用例时候都会重新打开,这样就会浪费很多时间.于是就想是不是可以只打开一 ...

  6. 就谈个py 的装饰器 decorator

    很早很早就知道有这么个 装饰器的东西,叫的非常神秘. 包括c#  和 java 中都有这个东西, c#中叫做attribut 特性,java中叫做Annotation 注解,在偷偷学习c#教程的时候, ...

  7. py基础4--迭代器、装饰器、软件开发规范

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1. 列表生成式,迭代器&生成器 列表生成式 我现在有个需求, ...

  8. Py修行路 python基础 (十)装饰器

    装饰器 一.定义 装饰器:顾名思义,就是对某个东西起到装饰修饰的功能. python中的装饰器,其本质上就是一个python函数,它可以让其他函数在不需要任何代码变动的前提下增加额外功能.通俗理解就是 ...

  9. [原创]django+ldap实现单点登录(装饰器和缓存)

    前言 参考本系列之前的文章,我们已经搭建了ldap并且可以通过django来操作ldap了,剩下的就是下游系统的接入了,现在的应用场景,我是分了2个层次,第一层次是统一认证,保证各个系统通过ldap来 ...

随机推荐

  1. Numpy的学习1-创建数据基础

    1 import numpy as np 2 3 array = np.array([[1,2,3],[4,5,6]]) 4 5 print(array) 6 print('number of dim ...

  2. Docker被替代 PodMan成为程序员新宠

  3. netsniff恶意流量识别和匹配解读

    代码整体框架 流量扫描函数调用 加载配置文件的代码调用 获取扫描的条数 重点匹配函数 流量eg:'\x00\x04\x00\x01\x00\x06\x00\x16>\x10\x1d>SW\ ...

  4. 利用Python将PDF文档转为MP3音频

    1. 转语音工具 微信读书有一个功能,可以将书里的文字转换为音频,而且声音优化的不错,比传统的机械朗读听起来舒服很多. 记得之前看到过Python有一个工具包,可以将文字转换为语音,支持英文和中文,而 ...

  5. Python面向对象:封装和多态

    一.封装 封装是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读取和修改的访问级别. 封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进 ...

  6. MQTT协议 局域网和广域网 云服务器和虚拟主机、VPS SSH和FTP、SFTP

     MQTT协议 MQTT协议就很好的解决了coap存在的问题.MQTT协议是由IBM开发的即时通讯协议,相比来说比较适合物联网场景的通讯协议.MQTT协议采用发布/订阅模式,所有的物联网终端都通过TC ...

  7. C#反编译工具ILSpy 反汇编

    ILSpy反编译工具之C#反汇编   1.下载ILspy工具 https://github.com/icsharpcode/ILSpy#ilspy------- 注意: ILspy需要在电脑上安装.N ...

  8. Spring-IOC基本使用

    通过上篇文章大概知道ioc.DI的概念了,下面我们详细介绍一下 一.Spring IOC创建对象 IOC通过上文的介绍作用是控制创建对象的解释权,我们把代码重新看一下 //User.java publ ...

  9. jsp中将一个jsp引入另一个jsp指定位置

    <jsp:include page="badSurveyUpdate.jsp"/>

  10. 在 ASP.NET Core和Worker Service中使用Quartz.Net

    现在有了一个官方包Quartz.Extensions.Hosting实现使用Quartz.Net运行后台任务,所以把Quartz.Net添加到ASP.NET Core或Worker Service要简 ...