函数和常用模块【day05】:装饰器高潮(三)
本节内容
1、概述
2、装饰器定义
3、装饰器定义
4、带参数的生成器
一、概述
我们之前介绍了大幅片的内容,感觉跟装饰器半毛钱关系都没有,其实不然,我们分别详细阐述了高阶函数和内置函数,下面我们就来讲讲什么是真正的装饰器。
二、装饰器定义
首先装饰器实现的条件:高阶函数+嵌套函数 =》装饰器
1、定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import time #定义内置函数 def timmer(func): #timmer(test1) func=test1 def deco(): start_time = time.time() func() #run test1() stop_time = time.time() print ( "the func run time is %s" % (stop_time - start_time)) return deco #装饰test1函数 @timmer # 相当于test1 = timmer(test1) def test1(): time.sleep( 3 ) print ( "in the test1" ) #直接执行test1函数 test1() #输出 in the test1 the func run time is 3.0002999305725098 |
执行步骤:
- 执行timmer函数,timmer(test1) 返回值赋值给test1变量,即test1=timmer(test1)
- 此时的test1的值是执行timmer函数返回值deco,即test1=deco
- 所以执行test1,其实就是执行的是deco函数,test1()其实就是执行deco函数。
2、执行函数带参数
我们先来试试,如果被装饰的函数需要传入参数怎么办?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import time def timmer(func): #timmer(test1) func=test1 def deco(): start_time = time.time() func() #run test1() stop_time = time.time() print ( "the func run time is %s" % (stop_time - start_time)) return deco @timmer def test2(name,age): print ( "name:%s,age:%s" % (name,age)) test2() #输出 Traceback (most recent call last): File "D:/PycharmProjects/pyhomework/day4/装饰器/装饰器高潮.py" , line 23 , in <module> test2() File "D:/PycharmProjects/pyhomework/day4/装饰器/装饰器高潮.py" , line 8 , in deco func() #run test1() TypeError: test2() missing 2 required positional arguments: 'name' and 'age' #缺少传入name和age参数 |
很显然是错误的,错误的。因为这边执行的test2函数其实就是执行的deco函数,deco函数体内的func()其实就是执行test2函数,但是,test2需要传入name和age两个参数,所以报错。那怎么解决呢?我们只能传入参数了,但是你又不能确定传入几个参数,所以我们只能用非固定参数传参。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
import time def timmer(func): #timmer(test1) func=test1 def deco( * args, * * kwargs): #传入非固定参数 start_time = time.time() func( * args, * * kwargs) #传入非固定参数 stop_time = time.time() print ( "the func run time is %s" % (stop_time - start_time)) return deco #不带参数 @timmer # 相当于test1 = timmer(test1) def test1(): time.sleep( 3 ) print ( "in the test1" ) #带参数 @timmer def test2(name,age): print ( "name:%s,age:%s" % (name,age)) #调用 test1() test2( "zhangqigao" , 22 ) #输出 #test1 in the test1 the func run time is 3.0010883808135986 #test2 name:zhangqigao,age: 22 the func run time is 0.0 #test2 |
三、执行函数有返回值
上面的例子,被调用的函数都没有返回值,那如果,我们被调函数有返回值,该如何做呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def timmer(func): #timmer(test1) func=test1 def deco( * args, * * kwargs): res = func( * args, * * kwargs) #这边传入函数结果赋给res return res # 返回res return deco @timmer def test1(): # test1 = timmer(test1) print ( "in the test1" ) return "from the test1" #执行函数test1有返回值 res = test1() print (res) #输出 in the test1 from the test1 |
通过上面的例子,可以看出,其实就是在内置函数中把传入参数的执行结果赋给res,然后再返回res变量。
四、带参数的装饰器
之前我们的装饰器都是没有带参数的,其实我们已经能解决90%的问题了,但是如果说有一种情况:就是在你访问不通页面时,你用的验证的方式来源不同,这时你该怎么办?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
#本地验证 user,passwd = "zhangqigao" , "abc123" def auth(auth_type): #传递装饰器的参数 print ( "auth func:" ,auth_type) def outer_wrapper(func): # 将被装饰的函数作为参数传递进来 def wrapper( * args, * * kwargs): #将被装饰函数的参数传递进来 print ( "wrapper func args:" , * args, * * kwargs) username = input ( "Username:" ).strip() password = input ( "Password:" ).strip() if auth_type = = "local" : if user = = username and passwd = = password: print ( "\033[32mUser has passed authentication\033[0m" ) res = func( * args, * * kwargs) print ( "--after authentication" ) return res else : exit( "Invalid username or password" ) elif auth_type = = "ldap" : pass return wrapper return outer_wrapper def index(): print ( "welcome to index page" ) @auth (auth_type = "local" ) #带参数装饰器 def home(): print ( "welcome to home page" ) return "from home" @auth (auth_type = "ldap" ) #带参数装饰器 def bbs(): print ( "welcome to bbs page" ) index() home() bbs() |
重上面的例子可以看出,执行步骤:
- outer_wrapper = auth(auth_type="local")
- home = outer_wrapper(home)
- home()
所以这个函数的作用分别是:
- auth(auth_type) 传递装饰器的参数
- outer_wrapper(func) 把函数当做实参传递进来
- wrapper(*args,**kwargs) 真正执行装饰的函数
函数和常用模块【day05】:装饰器高潮(三)的更多相关文章
- 小白的Python之路 day4 装饰器高潮
首先装饰器实现的条件: 高阶函数+嵌套函数 =>装饰器 1.首先,我们先定义一个高级函数,去装饰test1函数,得不到我们想要的操作方式 import time #定义高阶函数 def deco ...
- 探究functools模块wraps装饰器的用途
<A Byte of Python>17.8节讲decorator的时候,用到了functools模块中的一个装饰器:wraps.因为之前没有接触过这个装饰器,所以特地研究了一下. 何谓“ ...
- python进阶04 装饰器、描述器、常用内置装饰器
python进阶04 装饰器.描述器.常用内置装饰器 一.装饰器 作用:能够给现有的函数增加功能 如何给一个现有的函数增加执行计数的功能 首先用类来添加新功能 def fun(): #首先我们定义一个 ...
- 为什么 Python 没有函数重载?如何用装饰器实现函数重载?
英文:https://arpitbhayani.me/blogs/function-overloading 作者:arprit 译者:豌豆花下猫("Python猫"公众号作者) 声 ...
- Python初学者第二十三天 函数进阶(2)装饰器
装饰器: 需求----> 写一个功能,测试其他同事函数的调用效率. 第一版:功能版 import time def func(): time.sleep(0.2) print('非常复杂') d ...
- python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)
21.闭包 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量) 闭包的作用:1.保证数据的安全性(纯洁度).2.装饰器使用 .__closure__判断是否是闭包 def func(): a = ...
- 函数和常用模块【day05】:装饰器前奏(一)
本节内容 定义 原则 实现装饰器的储备知识 函数及变量 高阶函数 一.定义 1.装饰器:本质是函数. 2.功能:用来装饰其他函数,顾名思义就是,为其他的函数添加附件功能的. 二.原则 不能修改被装饰函 ...
- Day05:装饰器,三元表达式,函数的递归,匿名/内置函数,迭代器,模块,开发目录
上节课复习:1.函数的对象 函数可以被当作数据取处理2.函数嵌套 嵌套调用:在调用一个函数时,函数体代码又调用了其他函数 嵌套定义:在一个函数内部又定义了另一个函数 def foo( ...
- python函数与模块(装饰器,文件处理,迭代器等)
os模块 os.system('命令') 利用python调用系统命令,命令可以是以列表或者元组内的元素形式* res import os res=os.system('ipconfig') prin ...
随机推荐
- 《面向对象程序设计》c++第五次作业___calculator plus plus
c++第五次作业 Calculator plusplus 代码传送门 PS:这次作业仍然orz感谢一位同学与一位学长的windows帮助,同时再次吐槽作业对Mac系统用户的不友好.(没朋友千万别用Ma ...
- The MathType Dll cannot be found 问题解决办法
被这个问题困扰了许久,找到了解决办法,没想到最后居然是因为mathtype安装路径里的文件位置有问题(至少我是这么认为的).是这样的,在安装完mathtype6.9b后,发现打开word2013是正常 ...
- Neo4j初探
neo4j-desktop-win64 exe https://neo4j.com/download-thanks-desktop/?edition=desktop&flavour=winst ...
- Linux下安装oracle的过程
1. Linux 安装 主要不要将home分区设置的特别大 2. 安装必须的一些包. yum install -y \ binutils.x86_64 \ elfutils-libelf-devel. ...
- Windows下面dir 总是输入成ls的一个解决方法
转帖:http://blog.csdn.net/venusic/article/details/50543058 新建一个ls.bat文件 输入 @echo off dir 然后放到环境变量存在的一个 ...
- C++ 动态内存分配(6种情况,好几个例子)
1.堆内存分配 : C/C++定义了4个内存区间: 代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念: 通常定义变量(或对 ...
- 怎样让DBGrid在按住Shift点鼠标的同时能将连续范围的多行选中?
参见例子:…privateSel : Boolean ;//判断是否处于选择状态BookMark : TBookMark ;//记录先前的位置…procedure TForm1.DBGrid1Mous ...
- s - t 平面图最大流 (附例题 bzoj 1001)
以下均移自 周冬的<两极相通-浅析最大最小定理在信息学竞赛中的应用> 平面图性质 1.(欧拉公式)如果一个连通的平面图有n个点,m条边和f个面,那么f=m-n+2 2.每个平面图G都有一个 ...
- 16 利用Zabbix完成windows监控
点击返回:自学Zabbix之路 16 利用Zabbix完成windows监控 1.安装zabbix_agentd 1.1.下载zabbix_agentd监控客户端软件安装包(windows操作系统客户 ...
- 【转】安全加密(三):RFID标签防伪为生活开启安全模式
本文导读 随着RFID技术的快速发展和RFID电子标签的生产成本不断降低,RFID标签防伪技术的应用也得到了极大的普及,逐步出现在各行各业当中,如交通出行.票务安全.商品防伪等领域. RFID技术简介 ...