python里的装饰器
2011-10-25 17:25
513 查看
装饰器是一个函数,其主要用途是包装另一个函数或类。这种包装的首要目的是透明地修改或增强包装对象的行为。表示装饰器的语法是特殊符号@,如下所示:
上面的代码可以简化为:
这个例子中定义了函数square()。但在定义之后,函数对象本身就立即被传递给函数trace(),后者返回一个对象替代原始的square。现在,让我们考虑trace的实现,从而说明这样做的用处:
在这段代码中,trace()创建了写有一些调试输出的包装器函数。然后调用了原始函数对象。因此如果调用square()函数,看到的将是包装器中write()方法的输出。trace()函数返回的函数callf是一个闭包,用于替换原始的函数。关于这种实现的一个有趣方面是,跟踪功能本身只能像上面这样使用全局变量enable_tracing来启用。如果把这个变量设置为False,trace()装饰器只是返回未修改的原始函数。因此,禁用跟踪时,使用装饰器不会增加性能负担。
使用装饰器时,他们必须出现在函数或类定义之前的单独行上。可以同时使用多个装饰器,例如:
在这个例子中,装饰器按照他们出现的先后顺序应用,结果是:
装饰器也可以接受参数,例如:
如果提供参数,装饰器的语义如下所示:
在这个例子中,装饰器函数只接受带有@描述符的参数。它接着返回在调用时使用函数作为参数的函数。下面给出了一个例子:
装饰器也可以应用于类定义,例如:
对于类装饰器,应该让装饰器函数始终返回类对象作为结果。需要使用原始类定义的代码可能要直接引用类成员,如Bar.spam。如果装饰器函数foo()返回一个函数,这种引用就是不正确的
摘自:python参考手册第4版 6.5 节 82页
@trace def square(x): return x*x
上面的代码可以简化为:
def square(x): return x*x square = trace(square)
这个例子中定义了函数square()。但在定义之后,函数对象本身就立即被传递给函数trace(),后者返回一个对象替代原始的square。现在,让我们考虑trace的实现,从而说明这样做的用处:
enable_tracing = True if enable_tracing: debug_log = open('debug.log','w') def trace(func): if enable_tracing: def callf(*args, **kwargs): debug_log.write("Calling %s: %s, %s\n" % (func.__name__, args, kwargs)) r = func(*args, **kwargs) debug_log.write("%s returned %s\n" % (func.__name__, r)) return r return callf else: return func
在这段代码中,trace()创建了写有一些调试输出的包装器函数。然后调用了原始函数对象。因此如果调用square()函数,看到的将是包装器中write()方法的输出。trace()函数返回的函数callf是一个闭包,用于替换原始的函数。关于这种实现的一个有趣方面是,跟踪功能本身只能像上面这样使用全局变量enable_tracing来启用。如果把这个变量设置为False,trace()装饰器只是返回未修改的原始函数。因此,禁用跟踪时,使用装饰器不会增加性能负担。
使用装饰器时,他们必须出现在函数或类定义之前的单独行上。可以同时使用多个装饰器,例如:
@foo @bar @spam def grok(x): pass
在这个例子中,装饰器按照他们出现的先后顺序应用,结果是:
def grok(x): pass grok = foo(bar(spam(grok)))
装饰器也可以接受参数,例如:
@eventhandler('BUTTON') def handle_button(msg): ... @eventhandler('RESET') def handle_reset(msg): ...
如果提供参数,装饰器的语义如下所示:
def handle_button(msg): ... temp = eventhandler('BUTTON') #使用提供的参数调用装饰器 handle_button = temp(handle_button) #调用装饰器返回的函数
在这个例子中,装饰器函数只接受带有@描述符的参数。它接着返回在调用时使用函数作为参数的函数。下面给出了一个例子:
#事件处理程序装饰器 event_handlers = {} def eventhandler(event): def register_function(f): event_handlers[event] = f return f return register_function
装饰器也可以应用于类定义,例如:
@foo class Bar(object): def __init__(self, x): self.x = x def spam(self): statements
对于类装饰器,应该让装饰器函数始终返回类对象作为结果。需要使用原始类定义的代码可能要直接引用类成员,如Bar.spam。如果装饰器函数foo()返回一个函数,这种引用就是不正确的
摘自:python参考手册第4版 6.5 节 82页
相关文章推荐
- python -- 带有参数的装饰器
- Python中的装饰器用法详解
- 理解Python中的装饰器
- python初学 类以及装饰
- Python的高级特性7:闭包和装饰器
- python系列4之装饰器
- python与设计模式之二 装饰器模式(以dota为例)
- 简单理解Python中的装饰器
- 老生常谈Python进阶之装饰器
- python之装饰器
- python-装饰器
- Python 装饰器笔记
- Python 装饰器深入理解
- 传说中Python最难理解的点|看这完篇就够了(装饰器)
- 装饰器思想 由python联想到javascript
- 理解 Python 装饰器看这一篇就够了
- [Python]多个装饰器合并
- Python中的property() 函数 和@property 装饰符
- python学习笔记-装饰器1
- Python中的装饰器