一、什么是装饰器

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

器:器既函数

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

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

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

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

  1. Python成长之路【第九篇】:Python基础之面向对象

    一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程–>错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个人 ...

  2. (转)Python成长之路【第九篇】:Python基础之面向对象

    一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...

  3. 【Python成长之路】如何用python开发自己的iphone应用程序,并添加至siri指令

    哈喽大家好,我是鹏哥. 今天想记录的学习主题是 -- 基于pythonista3 app开发自己的iphone应用程序. ~~~上课铃~~~ (由于今天被小伙伴推荐了这首歌,因此就应他的要求,作为此文 ...

  4. python成长之路第三篇(2)_正则表达式

    打个广告欢迎加入linux,python资源分享群群号:478616847 目录: 1.什么是正则表达式,python中得正则简介 2.re模块的内容 3.小练习 一.什么是正则表达式(re) 正则表 ...

  5. python学习之路-第七天-python面向对象编程简介

    面向对象编程 在python中,同样是类和对象作为重要的组成部分. 而且在python中基本数据类型如int都是有封装类的,都有自己的方法,应该是和java里面的Integer类似吧 类包括域和方法: ...

  6. 我的Python成长之路---第三天---Python基础(13)---2016年1月16日(雾霾)

    五.Python的常用的内置函数 Python为我们准备了大量的内置函数,如下图所示 这里我们只讨论红框内的内置函数 abs(x) 返回一个数的绝对值(模),参数可以是真说或浮点数 >>& ...

  7. 我的Python成长之路---第三天---Python基础(9)---2016年1月16日(雾霾)

    一.集合 set和dict类似,也是一组key的集合,但不存储value.由于key不能重复,所以,在set中,没有重复的key. 集合和我们数学中集合的概念是一样的,也有交集,并集,差集,对称差集等 ...

  8. 我的Python成长之路---第五天---Python基础(17)---2016年1月30日(晴)

    常用模块 1.模块介绍 模块,用一砣代码实现了某个功能的代码集合. 模块分为三种 自定义模块 内置标准模块(又称标准库) 开源模块 2.常用模块 time模块 time.time() import t ...

  9. 【Python成长之路】破解Boss直聘网站滑块验证

    哈喽大家好,我是鹏哥. 今天要记录的内容是 -- 破解Boss直聘网站的滑块验证. -- 上 课 铃-- TuesdayBurak Yeter;Danelle Sandoval - Tuesday 1 ...

  10. 【Python成长之路】快速理解复制、浅拷贝、深拷贝

    哈喽大家好,我是鹏哥. 今天想聊聊的主题是 -- 浅拷贝/深拷贝. ~~~上课铃~~~ 赤伶HITA - 赤伶 1 写在前面 浅拷贝.深拷贝的知识点,在python笔试和面试的过程中,经常被作为考题来 ...

最新文章

  1. 生物工程学报-微生物组测序与分析专刊-邀请函
  2. 数据结构 互换二叉树中所有结点的左右子树 C
  3. 第一章 TensorFlow基础——python语法(三)
  4. What happens when passing an non-exist text object to API
  5. Desktop OS Market Share: Windows 90% - Mac 9% - Linux 1%
  6. Netcdf 文件多属性,按照时间段导出代码示例
  7. Visual SourceSafe(VSS)使用手册(转载)
  8. c 正则去掉html标签,C#用正则表达式去掉Html中的script脚本和html标签
  9. Caffe学习:使用pycaffe读取mean.binaryproto文件参数
  10. 2008下mysql补丁_windows Server 2008 R2安装Mysql 8的打补丁顺序
  11. JS获取ul中li的值同步到搜索框
  12. 计算机英语手抄报活动主题,英语手抄报比赛方案
  13. 苹果cms简洁精美影视模板整站源码
  14. java 微信小程序 校园跑腿系统
  15. java swing 大球吃小球游戏 功能完善 完整代码 下载即可以运行
  16. Spectator view——Hololens第三人称视角技术的详细实现过程
  17. 用JAVA详解冒泡排序
  18. S60手机系统错误对照表
  19. AI通过儿童眼球运动,筛查胎儿酒精谱系障碍
  20. 每日遥感论文(森林退化)

热门文章

  1. android 入门-android自定义控件
  2. jquery --- 使用when方法等待2个异步事件结束后执行某一个函数.
  3. es6 --- 正确获取Generator函数内部的this对象使其可以使用new
  4. Python 杨辉三角形的简单实现
  5. ES6-13 正则方法、修饰符yus、UTF_16编码方式
  6. ES5-拓展 箭头函数的this、this的优先级
  7. Codeforces Round #554 Div.2 E - Neko and Flashback
  8. Apache不记录制定文件类型日志
  9. Android自带Monkey测试
  10. WCF跨域 这可能是由于试图以跨域方式访问服务而又没有正确的跨域策略,或策略不适用于 SOAP...