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,一经查实,立即删除!

相关文章

php中改变函数路由,php – 如何修改codeigniter中的路由

我终于找到了我想要的东西.以下是我的代码在routes.php中的样子./* Custom Routes. */// Store Normal Pages.$route[home/(:any)] "base/home/$1";$route[about/(:any)] "base/about/$1";$route[services/(:any)] "base/services/$1";$route…

主域控宕机无法恢复后,如何配置辅助域控继续工作

情况如下: 系统基础结构如下:一个主域控,一个辅助域控且都安装AD与DNS集成区。 如果: 主域控宕机且无法恢复,请问辅助域应做些什么才能替代主域控继续工作? 第一步:在辅助域控上清除主域控AD数…

$.get、$.post 和 $().load()

一、$.get() 用于get方式进行异步请求。 结构: $.get( url, data, callback, type); url - 请求路径(string); data - 发送至服务器的键值对数据 (object); callback - 状态为success时的回调函数&a…

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

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

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

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

Symfony2

--开放性 --可扩展性 --持续升级性 --有商业背景和支持性 --被广泛使用性 --引领PHP领域最佳实践性 ----官网(查询功能使用) 定义类 类的属性和方法统称为类成员;类的实例化就是通过类的定义创建一个类的对象; 类定义》多个类得实…

oracle导出数据dummy,oracle导出表结构1

oracle导出表结构1.exp/imp工具在cmd中输入 exp username/password连接串回车,在进入如下时,输入no,就ok了导出表数据(yes/no):yes> no;补充----------------exp/imp工具;带参数:rowsy ——带…

Tree.Panel各项属性

1、Ext.tree.TreePanel主要配置项:root:树的根节点。rootVisible:是否显示根节点,默认为true。useArrows:是否在树中使用Vista样式箭头,默认为false。lines:是否显示树线,默认为true…

测试用例设计方法

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

oracle 在数据库打开状态下进行备份时_下面描述不正确的是,Oracle数据库DBA面试题50道及答案_经典...

Oracle数据库DBA面试题50道及答案_经典1. 解释冷备份和热备份的不同点以及各自的优点解答:热备份针对归档模式的数据库,在数据库仍旧处于工作状态时进行备份。而冷备份指在数据库关闭后,进行备份,适用于所有模式的数据库。热备份的…

Disk Quota磁盘配额

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

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

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

省选之前的未完成的计划(截至到省选)

PLAN OF THE COMING HEOI good problems:-bzoj4823:[Cqoi2017]老C的方块 【*】-bzoj3171:[Tjoi2013]循环格 【*】-bzoj4200:[Noi2015]小园丁与老司机 【*】-bzoj1061:[Noi2008]志愿者招募 【*】-bzoj3600:没有人的算术 【*】-bzoj2806:[Ctsc2012]Cheat 【*】-bzoj2219:数论之神…

动手写的Python的HTML语法分析器(面向对象)

动手写的Python的HTML语法分析器(面向对象) 主要包括4个文件,util.py文件主要负责截取每个块。 rules.py文件定义两个类,超类Rule和分别对应的子类,子类定义了不同的划分块的要求,子类包换action函数,调用h…

Linux中mysql的卸载和重装,在Linux下面卸载与重新安装Postgresql

在Linux下面卸载与重新安装Postgresql1. 先把原来的postgresql安装包找出来,如果找不到就可以直接安装了。[roottestserver postgresql]# rpm -qa|grep postpostgresql-docs-8.0.3-1.1AXpostgresql-libs-8.0.3-1.1AXfreeradius-postgresql-1.0.1-3.RHEL4.1AXpostgre…

[原]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 reset设定终端机的状态命令详解

名称: reset, tset使用方法: tset [-IQqrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]使用说明:reset 其实和 tset 是一同个命令,它的用途是设定终端机的状态。一般而言,这个命令会自动的从环境变数、命令列或是其它的组态档决定目前终端机的…

json-server模拟后台接口

前言: 项目开发中,影响项目进程的常常是由于在前后端数据交互的开发流程中停滞,前端完成静态页面的开发后,后端迟迟未给到接口。而现在,我们就可以通过根据后端接口字段,建立一个REST风格的API接口&#xf…

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

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