Python成长之路【第七篇】:Python基础之装饰器

一、什么是装饰器

装饰:装饰既修饰,意指为其他函数添加新功能

器:器既函数

装饰器定义:本质就是函数,功能是为其他函数添加新功能

二、装饰器需要遵循的原则

1、不能修改装饰器的源代码(开放封闭原则)

2、为装饰器函数添加新功能后,不能修改函数的调用方式

三、实现装饰器的知识储备

装饰器 = 高阶函数 + 函数嵌套 + 闭包

四、高阶函数 

高阶函数的定义:

1、函数接收的参数是一个函数名

2、函数的返回值是一个函数名

3、满足上述条件任意一个,都可以称为之高阶函数

 1 def foo():
 2     print('我的函数名作为参数传给高阶函数')
 3 def gao_jie1(func):
 4     print('我就是高阶函数1,我接收的参数名是%s' %func)
 5     func()
 6 
 7 def gao_jie2(func):
 8     print('我就是高阶函数2,我的返回值是%s' %func)
 9     return func
10 
11 gao_jie1(foo)
12 gao_jie2(foo)
高阶函数示范
 1 #高阶函数应用1:把函数名当做参数传给高阶函数
 2 import time
 3 def foo():
 4     print('from the foo')
 5 
 6 def timmer(func):
 7     start_time=time.time()
 8     func()
 9     stop_time=time.time()
10     print('函数%s 运行时间是%s' %(func,stop_time-start_time))
11 timmer(foo)
12 #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
把函数名当做参数传给高阶函数
 1 #高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
 2 import time
 3 def foo():
 4     print('from the foo')
 5 
 6 def timmer(func):
 7     start_time=time.time()
 8     return func
 9     stop_time=time.time()
10     print('函数%s 运行时间是%s' %(func,stop_time-start_time))
11 foo=timmer(foo)
12 foo()
13 #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
函数返回值是函数名

 

高阶函数总结:

1、函数接收的参数是一个函数名

  作用:在不修改函数源代码的前提下,为函数添加新功能

  不足:会改变函数的调用方式

2、函数的返回值是一个函数名

  作用:不修改函数的调用方式

  不足:不能添加新功能

 五、函数嵌套

def foo(name):print("from foo %s" %name)def ret():print("from ret")def bar():print("from bar")bar()ret()foo("Albert")

六、闭包

闭包:在一个作用域里放入定义变量,想当于打了一个包

def foo(name):def ret():print("123%s"%name)def bar():print("456%s"%name)bar()ret()foo("Albert")

七、没有参数的装饰器

没有参数的装饰器 = 高阶函数 + 函数嵌套

 

基本框架

# 这就是一个实现装饰器最基本的架子
def timer(func):def wrapper():func()return wrapper

 

加上参数

def timer(func):def wrapper(*args, **kwargs):func(*args, **kwargs)return wrapper

 

加上功能

import timedef timer(func):def wrapper(*args, **kwargs):s_time = time.time()func(*args, **kwargs)e_time = time.time()print("函数【%s】,运行的时间是%s"%(func, e_time - s_time))return wrapper

  

加上返回值

import timedef timer(func):def wrapper(*args, **kwargs):s_time = time.time()res = func(*args, **kwargs)e_time = time.time()print("函数【%s】,运行的时间是%s"%(func, e_time - s_time))return resreturn wrapper

  

使用装饰器

def cal(array):res = 0for i in array:res += ireturn rescal = timer(cal)
a = cal(range(10))
print(a)

 

语法糖@

@timer # @timer == cal = timer(cal)
def cal(array):res = 0for i in array:res += ireturn resa = cal(range(10))
print(a)

八、装饰器应用示例

 1 user_list=[
 2     {'name':'Albert','passwd':'123'},
 3     {'name':'Seven','passwd':'123'},
 4     {'name':'Eric','passwd':'123'},
 5     {'name':'Mary','passwd':'123'},
 6 ]
 7 
 8 current_user={'username':None,'login':False}
 9 
10 def auth_deco(func):
11     def wrapper(*args,**kwargs):
12         if current_user['username'] and current_user['login']:
13             res=func(*args,**kwargs)
14             return res
15         username=input('用户名: ').strip()
16         passwd=input('密码: ').strip()
17 
18         for index,user_dic in enumerate(user_list):
19             if username == user_dic['name'] and passwd == user_dic['passwd']:
20                 current_user['username']=username
21                 current_user['login']=True
22                 res=func(*args,**kwargs)
23                 return res
24         else:
25             print('用户名或者密码错误,重新登录')
26 
27     return wrapper
28 
29 @auth_deco
30 def index():
31     print('欢迎来到主页面')
32 
33 @auth_deco
34 def home():
35     print('这里是你家')
36 
37 def shopping_car():
38     print('查看购物车啊亲')
39 
40 def order():
41     print('查看订单啊亲')
42 
43 
44 index()
45 # home()
无参装饰器
 1 user_list=[
 2     {'name':'Albert','passwd':'123'},
 3     {'name':'Seven','passwd':'123'},
 4     {'name':'Eric','passwd':'123'},
 5     {'name':'Mary','passwd':'123'},
 6 ]
 7 
 8 current_user={'username':None,'login':False}
 9 def auth(auth_type='file'):
10     def auth_deco(func):
11         def wrapper(*args,**kwargs):
12             if auth_type == 'file':
13                 if current_user['username'] and current_user['login']:
14                     res=func(*args,**kwargs)
15                     return res
16                 username=input('用户名: ').strip()
17                 passwd=input('密码: ').strip()
18 
19                 for index,user_dic in enumerate(user_list):
20                     if username == user_dic['name'] and passwd == user_dic['passwd']:
21                         current_user['username']=username
22                         current_user['login']=True
23                         res=func(*args,**kwargs)
24                         return res
25                 else:
26                     print('用户名或者密码错误,重新登录')
27             elif auth_type == 'ldap':
28                 print('巴拉巴拉小魔仙')
29                 res=func(*args,**kwargs)
30                 return res
31         return wrapper
32     return auth_deco
33 
34 
35 #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
36 #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
37 @auth(auth_type='file')
38 def index():
39     print('欢迎来到主页面')
40 
41 @auth(auth_type='ldap')
42 def home():
43     print('这里是你家')
44 
45 def shopping_car():
46     print('查看购物车啊亲')
47 
48 def order():
49     print('查看订单啊亲')
50 
51 index()
52 # home()
带参装饰器

 九、超时装饰器

  1 import sys,threading,time
  2 
  3 class KThread(threading.Thread):
  4 
  5     """A subclass of threading.Thread, with a kill()
  6 
  7     method.
  8 
  9 
 10 
 11     Come from:
 12 
 13     Kill a thread in Python:
 14 
 15     http://mail.python.org/pipermail/python-list/2004-May/260937.html
 16 
 17     """
 18 
 19     def __init__(self, *args, **kwargs):
 20 
 21         threading.Thread.__init__(self, *args, **kwargs)
 22 
 23         self.killed = False
 24 
 25 
 26 
 27     def start(self):
 28 
 29         """Start the thread."""
 30 
 31         self.__run_backup = self.run
 32 
 33         self.run = self.__run      # Force the Thread to install our trace.
 34 
 35         threading.Thread.start(self)
 36 
 37 
 38 
 39     def __run(self):
 40 
 41         """Hacked run function, which installs the
 42 
 43         trace."""
 44 
 45         sys.settrace(self.globaltrace)
 46 
 47         self.__run_backup()
 48 
 49         self.run = self.__run_backup
 50 
 51 
 52 
 53     def globaltrace(self, frame, why, arg):
 54 
 55         if why == 'call':
 56 
 57           return self.localtrace
 58 
 59         else:
 60 
 61           return None
 62 
 63 
 64 
 65     def localtrace(self, frame, why, arg):
 66 
 67         if self.killed:
 68 
 69           if why == 'line':
 70 
 71             raise SystemExit()
 72 
 73         return self.localtrace
 74 
 75 
 76 
 77     def kill(self):
 78 
 79         self.killed = True
 80 
 81 
 82 
 83 class Timeout(Exception):
 84 
 85     """function run timeout"""
 86 
 87 
 88 
 89 def timeout(seconds):
 90 
 91     """超时装饰器,指定超时时间
 92 
 93     若被装饰的方法在指定的时间内未返回,则抛出Timeout异常"""
 94 
 95     def timeout_decorator(func):
 96 
 97         """真正的装饰器"""
 98 
 99 
100 
101         def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):
102 
103             result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))
104 
105 
106 
107         def _(*args, **kwargs):
108 
109             result = []
110 
111             new_kwargs = { # create new args for _new_func, because we want to get the func return val to result list
112 
113                 'oldfunc': func,
114 
115                 'result': result,
116 
117                 'oldfunc_args': args,
118 
119                 'oldfunc_kwargs': kwargs
120 
121             }
122 
123             thd = KThread(target=_new_func, args=(), kwargs=new_kwargs)
124 
125             thd.start()
126 
127             thd.join(seconds)
128 
129             alive = thd.isAlive()
130 
131             thd.kill() # kill the child thread
132 
133             if alive:
134 
135                 raise Timeout(u'function run too long, timeout %d seconds.' % seconds)
136 
137             else:
138 
139                 return result[0]
140 
141         _.__name__ = func.__name__
142 
143         _.__doc__ = func.__doc__
144 
145         return _
146 
147     return timeout_decorator
148 
149 
150 @timeout(5)
151 
152 def method_timeout(seconds, text):
153 
154     print('start', seconds, text)
155 
156     time.sleep(seconds)
157 
158     print('finish', seconds, text)
159 
160     return seconds
161 
162 
163 method_timeout(6,'asdfasdfasdfas')
查看代码

 

转载于:https://www.cnblogs.com/albert0924/p/8760575.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267294.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql数据库与oracle数据库同步,[sql数据库同步]Oracle与SQL Server如何实现表数据同步...

在线QQ客服:1922638专业的SQL Server、MySQL数据库同步软件数据库的Oracle版本为10.2,并安装在Linux系统上。数据库SQL Server的版本是SQL 2005,已安装在Windows XP系统上。现在我们需要做的是在两个数据库表之间同步数据。现在,最…

零食嘴----美食领域的美丽说

零食嘴美食分享社区首页 阿里巴巴参谋长曾鸣曾说过:“淘宝等美丽说模式整整等了两年。不仅在女性领域,阿里希望在各个维度都出现‘美丽说’。” 零食嘴就是美食领域美丽说。 所谓的美丽说模式,是指社会化电子商务分享的模式,在一个…

测试用例设计方法

测试用例设计方法 本篇由本人整理黑盒、白盒、接口测试一系列用例设计方法。 黑盒测试用例设计方法包括等价类划分法、边界值分析法、错误推测法、因果图法、判定表驱动法、正交试验设计法、功能图法、场景图法等。 (一)等价类划分法 定义:等…

Disk Quota磁盘配额

Disk Quota :磁盘配额 限制某个用户或某个组,对某个分区(生效级别是文件系统)的使用能力;由于早期的Unix系统是多用户、多任务的环境,所以一台主机的磁盘会被多个用户使用,某个用户占用大量的磁盘空间会影响其他用户对…

linux进度条脚本,Linux下简易进度条的实现代码

在生活中,进度条是很常见的,那么,进度条是如何实现的呢?首先,进度条的动态是利用人眼视觉暂留效果的。实际上是如下过程:先输出:[ ]表示进度是1%,刷新之后再输出:[ …

[原]Jenkins(二十) jenkins再出发之Error: Opening Robot Framework log failed

错误缘由:使用plugin [public robot framework test results] 生成的HTML文件都无法正常打开.解决方案:Connect on your jenkins url (http://[IP]:8080/) Click on administer Jenkins Click on consol jenkins Copy this into the field and execut…

【016】VS2010连接内置SQL数据库

参考:传智播客.Net培训.net视频教程 >> 【05】第五季 ADO.NET(1-30) 示例代码:sql_test.zip 首先建立一个 控制台 或者 WinForm 项目,然后进行下面的操作! 1. 在 项目 上面右键》添加》新建项 2. 接下…

为什么生产环境都是linux,关于生产环境linux系统中的wheel用户组

本文系统环境:CentOS Linux release 7.7.1908 (Core)一般来说,目前linux系统中的wheel组,默认情况是没有使用到的、如果要使用wheel组,让其有具体的作用,需要结合/etc/pam.d/su文件配置很多在Linux中为了更进一步加强系…

微信小程序----全局变量

全局变量的作用 在微信小程序开发中,会遇到一个很实际的应用场景,就是一个变量会在多个页面进行使用。 例如: 1. 在微信小程序开发中使用高德地图的微信小程序开发,其中key值就需要在多个页面使用; 2. 在微信小程序开…

linux centos-6.5,Linux(CentOS 6.5)安装 mysql

linux下安装软件的方式很多,这里是使用简单而方便的yum来安装一、使用yum 安装mysql服务,客户端1、检查是否已经安装: yum list installed | grep mysql2、 yum list installed | grep MYSQL3、查询结果:4、这是我已经安装的mysq…

amcharts应用

查看选中的软件的下载量,通过amchart报表工具显示出软件日下载量,月下载量以及年下载量,下面简单介绍,amchart在struts2中的应用。 amCharts提供JavaScript/HTML5图表。一套包括串行(列,栏,线&a…

linux下makefile中cp,make与makefile 的理解

当我们写程序过程中存在多个文件之间有复杂的包含关系时,若修改了其中一个源文件,就重新编译所有文件,一般是不必要的,并且当文件很多时,就显得非常笨拙。所有包含该文件的文件需要重新编译,而其它无关系的…

keil用c语言怎么编辑器,用keil软件编写单片机程序的步骤

猜你感兴趣:新手教程:单片机的学习实践步骤运用单片机便是了解单片机硬件结构,以及内部资源的运用,在汇编或C语言中学会各种功用的初始化设置,以及完成各种功用的程序编制。 运用按钮输入信号,发光二极管显…

体重 年龄 性别 身高 预测鞋码_【新手扫盲】身高体重性别年龄身体素质影响玩滑板吗?...

很多新手在迈入滑板大门之前都会有诸多顾虑,以为滑板跟其他运动一样,门槛很高我想说,滑板是项自由友好的运动下到3岁小宝宝,上到60岁以上老人只要你想玩,那就可以参与进来没有任何因素能阻止你玩滑板1、你比他高吗&…

html5点击按钮出现弹窗 怎么实现_HTML5游戏开发过程中的二三事

文/ Luiu最近跟的一款项目是HTML5手游,在这个项目中遇到并解决了诸多问题,也学习到了很多项目开发过程中需要注意的事情。这个项目自立项到现在已经过了5个多月,如今项目研发已经过了早期的忙乱阶段,于是借此机会梳理下思绪&#…

HDU 2063 过山车【二分图最大匹配】

Problem DescriptionRPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有…

科研入门之在web of science

ISI Web of Science是全球最大、覆盖学科最多的综合性学术信息资源,收录了自然科学、工程技术、生物医学等各个研究领域最具影响力的超过8700多种核心学术期刊。利用Web of Science丰富而强大的检索功能-普通检索、被引文献检索、化学结构检索,可以方便快…

手动生成 XML

2019独角兽企业重金招聘Python工程师标准>>> private void Button1_Click(object sender, System.EventArgs e) { //创建新的xml XmlDocument doc new XmlDocument(); doc.LoadXml("<company></company>"); //设置版本信息 XmlDeclaration x…

android 资源如何下沉,个推安卓手机报告: 华为一路领跑,OV下沉市场表现不俗

近日&#xff0c;国内专业的数据智能服务商个推(股票代码&#xff1a;每日互动 300766.sz)发布《 2019 年度安卓智能手机报告》&#xff0c;对华为、小米、OPPO、vivo、三星等国内主要智能手机品牌进行盘点。数据显示&#xff0c;华为手机 2019 年表现不俗&#xff0c;不仅以25…

ISA Server 2006 升级到 TMG2010

ISA Server的下个版本TMG2010已经发布有一段时间了&#xff0c;现在正在逐渐将原来的ISA Server 2006升级到TMG2010。由于TMG2010需要64位的CPU与Windows Server 2008操作系统&#xff0c;所以&#xff0c;如果原来的ISA Server 2006是安装在32位的CPU的服务器中&#xff0c;则…