Python学习笔记:装饰器
2019-01-10 07:50:11来源:博客园 阅读 ()
Python 装饰器的基本概念和应用
- 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
- 封闭:已实现的功能代码块
- 开放:对扩展开发
装饰器是 Python 高阶函数的语法糖,可以为已经存在的对象添加额外的功能,比如:
- 引入日志
- 函数执行时间统计
- 执行函数前预备处理
- 执行函数后清理功能
- 权限校验等场景
- 缓存
Python 装饰器的基本实现
装饰器的例程:
1 #!/usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 #File Name:04_decorator_simple.py 4 #Created Time:2019-01-09 15:24:38 5 6 7 import time 8 9 10 def timefun(func): 11 # wrapped_fun 即为闭包, func 为要装饰的函数 12 def wrapped_fun(): 13 start_time = time.time() 14 func() 15 end_time = time.time() 16 print("%s\t运行用时 %f s" % (func.__name__, end_time - start_time)) 17 return wrapped_fun # 返回内部函数的引用 18 19 20 def foo1(): 21 for i in range(10000): 22 pass 23 24 25 @timefun # 相当于 foo = timefun(foo) 26 def foo(): 27 for i in range(100000): 28 pass 29 30 31 if __name__ == "__main__": 32 foo1 = timefun(foo1) 33 foo1() 34 foo()
foo1 运行用时 0.000491 s
foo 运行用时 0.002976 s
运行过程分析见下图:
Python 装饰器实现的基础为闭包,其会在闭包中调用目标函数,关于闭馆的详细内容,请参考 Python 学习笔记:闭包
Python 装饰器的使用
多个装饰器
1 #!/usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 #File Name:05_decorator_multi.py 4 #Created Time:2019-01-09 15:55:31 5 6 7 def make_body(func): 8 """添加 body""" 9 def wrapped(): 10 return "<b>" + func() + "</b>" 11 return wrapped 12 13 14 def make_italic(func): 15 """设置为斜体""" 16 def wrapped(): 17 return "<i>" + func() + "</i>" 18 return wrapped 19 20 # 相当于 make_body(make_italic(foo)) 21 @make_body 22 @make_italic 23 def foo(): 24 return "Hello World" 25 26 def foo1(): 27 return "Hello Python" 28 29 30 if __name__ == "__main__": 31 print(foo()) 32 foo1 = make_body(make_italic(foo1)) 33 print(foo1())
<b><i>Hello World</i></b> <b><i>Hello Python</i></b>
多个装饰器的运行过程分析:
含有不定长参数
1 #!/usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 #File Name:06_decorator_multi_var.py 4 #Created Time:2019-01-09 16:20:30 5 6 7 from time import ctime 8 9 10 def timefun(func): 11 def wrapped_func(*args, **kwargs): 12 print("%s called at %s" % (func.__name__, ctime())) 13 print("wrapped_func: ", end="") 14 print(args, kwargs) 15 func(*args, **kwargs) # 拆包 16 return wrapped_func 17 18 19 @timefun 20 def foo(a,b,*args, **kwargs): 21 print("foo: %s, %s, %s, %s" %(a, b, args, kwargs)) 22 23 24 if __name__ == "__main__": 25 foo(1,2,3,4,5, tmp=2)
foo called at Wed Jan 9 16:32:48 2019 wrapped_func: (1, 2, 3, 4, 5) {'tmp': 2} foo: 1, 2, (3, 4, 5), {'tmp': 2}
带有返回值
1 #!/usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 #File Name: 07_decorator_multi_retrun.py 4 #Created Time:2019-01-09 16:20:30 5 6 7 from time import ctime 8 9 10 def timefun(func): 11 def wrapped_func(*args, **kwargs): 12 print("%s called at %s" % (func.__name__, ctime())) 13 print("wrapped_func: ", end="") 14 print(args, kwargs) 15 return func(*args, **kwargs) # 此处如何没有 return,则26行会输出 None 16 return wrapped_func 17 18 19 @timefun 20 def foo(a,b,*args, **kwargs): 21 print("foo: %s, %s, %s, %s" %(a, b, args, kwargs)) 22 return "Hello world!" 23 24 25 if __name__ == "__main__": 26 print(foo(1,2,3,4,5, tmp=2))
foo called at Wed Jan 9 16:38:05 2019 wrapped_func: (1, 2, 3, 4, 5) {'tmp': 2} foo: 1, 2, (3, 4, 5), {'tmp': 2} Hello world!
装饰器中设置外部变量
1 #!/usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 #File Name: 08_decorator_outside_var.py 4 #Created Time:2019-01-09 16:20:30 5 6 7 def timefun_arg(outside_var="Hello"): 8 def timefun(func): 9 def wrapped_func(*args, **kwargs): 10 print("wrapped_func: %s" % outside_var) 11 return func(*args, **kwargs) 12 return wrapped_func 13 return timefun 14 15 16 @timefun_arg() 17 def foo(a,b,*args, **kwargs): 18 return "foo: Hello world!" 19 20 21 @timefun_arg("Python") # 相当于 foo1 = timefun_arg("Python")(foo1) 22 def foo1(a,b,*args, **kwargs): 23 return "foo1: Hello world!" 24 25 26 if __name__ == "__main__": 27 print(foo(1,2,3,4,5, tmp=2)) 28 print(foo1(1,2,3,4,5, tmp=2))
定义多层函数,相当于双层的装饰器。
wrapped_func: Hello
foo: Hello world!
wrapped_func: Python
foo1: Hello world!
类装饰器
1 #!/usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 #File Name:09_decorator_class.py 4 #Created Time:2019-01-09 16:53:33 5 6 7 class Test(object): 8 def __init__(self, func): 9 print("******初始化******") 10 print("Called by %s." % func.__name__) 11 self.func = func 12 13 def __call__(self): 14 return self.func() 15 16 17 @Test # 相当于 foo = Test(foo) 18 def foo(): 19 return "Hello world!" 20 21 def foo1(): 22 return "Hello python!" 23 24 if __name__ == "__main__": 25 print(foo()) 26 foo1 = Test(foo1) 27 print(foo1())
类对象借助 __call__() 魔术方法,即可实现相应的类装饰器
******初始化****** Called by foo. Hello world! ******初始化****** Called by foo1. Hello python!
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python3基础之“术语表(2)” 2019-08-13
- python3 之 字符串编码小结(Unicode、utf-8、gbk、gb2312等 2019-08-13
- Python3安装impala 2019-08-13
- 小白如何入门 Python 爬虫? 2019-08-13
- python_字符串方法 2019-08-13
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash