python里的装饰器

     装饰器是一个函数,其主要用途是包装另一个函数或类。这种包装的首要目的是透明地修改或增强包装对象的行为。表示装饰器的语法是特殊符号@,如下所示:

@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页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值