Learing Python 装饰器 Decorator

来源:互联网 发布:中国数据挖掘会议 编辑:程序博客网 时间:2024/06/08 19:22

     在flask的文档的例子中有这样的语句:

@app.route('/')
def hello_world():

@app.route('/add', methods = ['POST'])

很好奇这是什么玩意儿,查了coolshell的一篇文章和这里的这里的文章知道了这是装饰器(decorator),感觉前面参考文献的例子略乱,我自己写了一个函数装饰器和类装饰器的例子便于理解。

引用coolshell里的Python修饰器的函数编程(http://coolshell.cn/articles/11265.html)里面描述的Python装饰器的本质:

Decorator 的本质

对于Python的这个@注解语法糖- Syntactic Sugar 来说,当你在用某个@decorator来修饰某个函数func时,如下所示:

@decoratordef func():    pass

其解释器会解释成下面这样的语句:

func = decorator(func)

那如何使用装饰器呢?

对于函数的装饰器,需要实现被装饰的函数的decorator函数,在decorator函数会接收被传递过来的函数作为自己的参数,同时需要定义一个wrapper函数,它可以接收被装饰函数传递过来的参数(有两层函数了),最后返回wrapper函数给被装饰函数;如果装饰器自身有参数呢?那么需要在外层包装一个函数来接收decorator的参数(有三层函数了)。

对于类的装饰器,需要实现被装饰的函数的decorator类,对于无参数的decorator,__init__方法会接收被装饰函数,__call__会接收被装饰函数的参数并返回自己给被装饰函数;对于有参数的decorator,__init__方法会接收decorator参数,__call__会接收被装饰函数,所以需要在__call__中定义一个wrapper来接收被装饰函数的参数。

听起来有点绕所以结合代码来看更加清晰。

函数decorator示例代码

def fuck_decorator(f):print 'decorating', f.__name__f()return None #f would be assigned NoneType objectdef suck_decorator(f):print 'decorationg', f.__name__def wrapper(*args):print __name__, argsreturn wrapperdef para_decorator(**kargs): # get para from decorator print 'para_decorator kargs are', kargsdef real_decorator(f):method = kargs['method']if method == 'fuck':def wrapper(): # wrapper is a must or para_fuck/para_bitch would be NoneType ojbectprint 'method is', kargs['method']return wrapperif method == 'bitch':def wrapper(*args):print 'para_bitch args are', argsf(method)return wrapperreturn real_decorator@fuck_decoratordef fuck():pass@suck_decoratordef suck():pass@para_decorator(method = 'fuck')def para_fuck():pass@para_decorator(method = 'bitch')def para_bitch(*args):print args[0], 'you'if __name__ == '__main__':# fuck() fuck_decorator return None and fuck 'NoneType' object is not callablesuck('fuck')para_fuck()para_bitch('hello')


类decorator示例代码

class MyDecorator:"fuck() is decorate in __init__ and return __call__ back to itself"def __init__(self, f):print 'begin to decorate', f.__name__self.f = fprint 'end decorate', f.__name__def __call__(self, *args):print '__call__ has been assgined to', self.f.__name__, argsclass ParaDecorator:def __init__(self, **kargs):print 'ParaDecorator kargs arg', kargsself.method = kargs['method']def __call__(self, f):def wrapper(*args):print 'para_fuck args are', argsf(self.method, method = self.method)return wrapper@MyDecoratordef fuck(*args):print 'fuck bitch'@ParaDecorator(method = 'fuck')def para_fuck(*args, **kargs):print args[0], 'you'print 'method is', kargs['method']# fuck was decorated before __main__ and fuck = MyDecorator(fuck).__call__if __name__ == '__main__':print MyDecorator.__doc__fuck()fuck('fuck')para_fuck()para_fuck('hello')



0 0
原创粉丝点击