装饰器:

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. 手把手教你搭饥荒专用服务器(三)—MOD及其他高级设置

    友情链接: 手把手教你搭饥荒专用服务器(一)-服务器准备工作 手把手教你搭饥荒专用服务器(二)-环境配置及基本使用 手把手教你搭饥荒专用服务器(三)-MOD及其他高级设置 手把手教你搭饥荒专用服务器( ...

  2. python序列(一)列表的增加

    列表是python中内置有序可变序列,列表的所有元素放在一堆中括号"{}"中,并使用逗号隔开 1.列表的创建 使用"="直接创建一个列表 >>> ...

  3. 微服务痛点-基于Dubbo + Seata的分布式事务(TCC模式)

    前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...

  4. java中远程调用接口springboot

    package com.kakarote.crm.utils; import cn.hutool.core.util.ObjectUtil; import org.apache.http.client ...

  5. [数据库]000 - 🍳Sysbench 数据库压力测试工具

    000 - Sysbench 数据库压力测试工具 sysbench 是一个开源的.模块化的.跨平台的多线程性能测试工具,可以用来进行CPU.内存.磁盘I/O.线程.数据库的性能测试.目前支持的数据库有 ...

  6. docker 安装 运行 卸载

    一.卸载docker 安装时使用什么工具安装的docker就用什么工具卸载docker: 1.yum卸载docker 查看已安装的docker yum list installed | grep do ...

  7. Layui关闭弹出层对话框--刷新父界面

    在毕设的开发中,添加用户.添加权限等等一些地方需要类似于bootstrap中的模态框.然而开发用的却是layui 在layui中有弹出层可以实现其中的效果. 但是,一般用的时候都是提交后关闭窗口,刷新 ...

  8. JavaDailyReports10_18

    学习内容:HTML基本知识 1.通常标记具有默认属性,当一个标记中只有标记名时,使用默认属性. 2.HTML标记有两种:单标记和双标记,单标记的语法格式:  <标记名称/> 3.不同的属性 ...

  9. Spring—SSJ集成&声明式事务管理

    1.   课程介绍 1.  SSJ集成;(掌握) 2.  声明式事务管理;(掌握) 什么是三大框架 2.1.  ssh Struts/Struts2 Spring Hibernate 2.2.  ss ...

  10. 30天自制操作系统-day1

    30天自制操作系统(linux环境)--第一天 我是在CentOS的环境上面实现的,使用ubuntu的环境也是类似的 第一步:因为要对二进制文件进行编辑,所以安装二进制编辑器hexedit(当然其他的 ...