装饰器:

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. Lua的require小结

    在游戏开发中会经常使用到lua作为游戏逻辑层的脚本语言,各种优势就不说了,虽然平时用的比较多,但对lua语言本身和内部的一些实现并不是很了解,让我们先从lua的require入手来一探require的 ...

  2. 卷积涨点论文 | Asymmetric Convolution ACNet | ICCV | 2019

    文章原创来自作者的微信公众号:[机器学习炼丹术].交流群氛围超好,我希望可以建议一个:当一个人遇到问题的时候,有这样一个平台可以快速讨论并解答,目前已经1群已经满员啦,2群欢迎你的到来哦.加入群唯一的 ...

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

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

  4. rocketMq broker.conf全部参数解释

    #4.7.1版本 #所属集群名字brokerClusterName=rocketmq-cluster#broker名字,名字可重复,为了管理,每个master起一个名字,他的slave同他,eg:Am ...

  5. RHCE <复习RHSCA>

    什么是shell? shell是你(用户)和Linux(或者更准确的说,是你和Linux内核)之间的接口程序,你在提示符下输入的每个命令都由shell先解释然后传给Linux内核. bash 是大多数 ...

  6. sql中大于等于小于的写法

    由于在mybatis框架的xml中<= , >=解析会出现问题,编译报错,所以需要转译第一种写法: 原符号 < <= > >= & ' "替换符号 ...

  7. JAVA十大经典排序算法最强总结(含JAVA代码实现)

    0.排序算法说明 0.1 排序的定义 对一序列对象根据某个关键字进行排序. 0.2 术语说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面: 不稳定:如果a原本在b的前面,而a=b,排 ...

  8. Linux音频编程--使用ALSA库播放wav文件

    在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例. 案例代码: /** *test.c * *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功. * */ #inclu ...

  9. Java 为每个原始类型提供了哪些包装类型:

    java的包装类型: 原始类型: boolean,char,byte,short,int,long,float,double 包装类型:Boolean,Character,Byte,Short,Int ...

  10. CentOS 6或7 启动故障修复及root密码破解

    CentOS 6或7 启动故障修复及root密码破解 目录 CentOS 6或7 启动故障修复及root密码破解 CentOS 6启动流程修复: 实验一:删除initramfs-2.6.32-754. ...