Python中的装饰器decorator
2015-11-05 21:31
459 查看
本文是一篇读书笔记,写于一年多前。原文为:http://coolshell.cn/articles/11265.html 本文只是对其中基础和重要部分的选取与简化。
1. 函数Decorator的本质:
举例:
原先的foo函数被hello这个decorator包裹(wrap)了一层了。
故多个Decorator其实是如下的转换:
2. 带参数的Decorator:
3. class式的Decorator
输出:
4. Decorator的副作用
被decorator的函数其实已经是另外一个函数了。如果查询一下被decorator之后的原函数名(如foo.__name__)的话,你会发现其输出的是“wrapper”(decorator的函数名),而不是我们期望的“foo”(原函数名),这可能会给将来的程序埋一些坑。
所以,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。
wraps的作用就是把原函数的函数名等属性传递给decorator函数。
5. 经典的例子
给函数调用做缓存:
执行结果如下:
1. 函数Decorator的本质:
@one_decorator def func(): pass # 相当于 func = one_deacorator(func)
举例:
def hello(fn): def wrapper(): print "hello, %s" % fn.__name__ fn() print "goodbye, %s" % fn.__name__ return wrapper @hello def foo(): print "i am foo"
原先的foo函数被hello这个decorator包裹(wrap)了一层了。
故多个Decorator其实是如下的转换:
@decorator_one @decorator_two def func(): pass # 相当于 func = decorator_one(decorator_two(func))
2. 带参数的Decorator:
@decorator(arg1, arg2) def func(): pass 相当于 func = decorator(arg1,arg2)(func)注意:这里因为decorator(arg1,arg2)返回的是一个类似函数指针的东西,也就是一个函数,所以func就作为了这个函数的参数了。
3. class式的Decorator
class myDecorator(object): def __init__(self, fn): print "inside myDecorator.__init__()" self.fn = fn def __call__(self): self.fn() print "inside myDecorator.__call__()" @myDecorator def aFunction(): print "inside aFunction()" print "Finished decorating aFunction()" aFunction()
输出:
inside myDecorator.__init__() Finished decorating aFunction() inside aFunction() inside myDecorator.__call__()
4. Decorator的副作用
被decorator的函数其实已经是另外一个函数了。如果查询一下被decorator之后的原函数名(如foo.__name__)的话,你会发现其输出的是“wrapper”(decorator的函数名),而不是我们期望的“foo”(原函数名),这可能会给将来的程序埋一些坑。
所以,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。
wraps的作用就是把原函数的函数名等属性传递给decorator函数。
from functools import wraps def hello(fn): @wraps(fn) def wrapper(): print "hello, %s" % fn.__name__ fn() print "goodbye, %s" % fn.__name__ return wrapper @hello def foo(): '''foo help doc''' print "i am foo" pass foo() print foo.__name__ #输出 foo print foo.__doc__ #输出 foo help doc
5. 经典的例子
给函数调用做缓存:
from functools import wraps def memo(fn): cache = {} miss = object() @wraps(fn) def wrapper(*args): result = cache.get(args, miss) if result is miss: result = fn(*args) cache[args] = result else: print "Hit Cache! - %s" % args return result return wrapper @memo def fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2)
执行结果如下:
>>> execfile("1.py") >>> fib(10) Hit Cache! - 1 Hit Cache! - 2 Hit Cache! - 3 Hit Cache! - 4 Hit Cache! - 5 Hit Cache! - 6 Hit Cache! - 7 Hit Cache! - 8 55 >>> fib(10) Hit Cache! - 10 55 >>> fib(8) Hit Cache! - 8 21
相关文章推荐
- Python shutil模块
- python开发_xml.etree.ElementTree_XML文件操作_该模块在操作XML数据是存在安全隐患_慎用
- pylearn2 安装及测试 windows 7 64bit
- python正则表达式
- python关于 date的使用
- winpython安装
- python+Eclipse+pydev环境搭建
- 为什么学习Python
- 初识Python
- opencv + numpy for python
- Python实现plist图片的裁切
- python 学习笔记(07)
- python fabric实现远程操作和部署
- 如何面试Python后端工程师?
- 【window10下notepad++编程软件配置python编程环境详细图文教程】
- python实现逻辑回归
- python学习
- vim 创建Python脚本时候自动补全解释器和编码方法
- python安装pip
- Python 列表中存储类对象时按照指定属性进行排序——用于正排表的排序