1. 在Design Patten中的一种设计模式叫Decorator,翻译成中文就是装饰器。
2. 在Python里也有类似的概念,例如
@staticmethod
@classmethod
@property
3. 它们用来装饰一个方法,以便以给方法添加额外的行为
4. 这节来分析一下Python里的decorator的使用方法
5. 在Kivy中,如pyjnius代码中,大量的用到了自定义的Decorator,如@java_method,@run_on_ui_thread等等
6. 首先说明一下,decorator可以是一个自定义的类,也可以是一个自定义的函数,接下来通过例子来分析它的使用方法。
7. 先来看一个自定义类作为decorator的例子:
class HelloDecorator: def __init__(self, *args): print 'HelloDecorator.__init__',args self.f = args[0] def __call__(self, *args): print '+++++++++++++++++HelloDecorator.__call__++++++++++++++',args self.f(*args) class GoodbyeDecorator: def __init__(self, *args): print 'GoodbyeDecorator.__init__',args def __call__(self, func): print '+++++++++++++++++GoodbyeDecorator.__call__++++++++++++++',func return func class A(object): @HelloDecorator def SayHello(person): print 'hello,',person @GoodbyeDecorator('abc') def SayGoodbye(self, person): print 'goodbye,',person print '+++++++++++++++++++++' listener = A() print '----------------------' listener.SayHello('world'); listener.SayGoodbye('world');
7.1 运行后我们将得到下面的打印:
HelloDecorator.__init__ (<function SayHello at 0x0267D670>,) GoodbyeDecorator.__init__ ('abc',) +++++++++++++++++GoodbyeDecorator.__call__++++++++++++++ <function SayGoodbye at 0x0267D6B0> +++++++++++++++++++++ ---------------------- +++++++++++++++++HelloDecorator.__call__++++++++++++++ ('world',) hello, world goodbye, world
7.2 从中我们可以得到如下的信息:
7.2.1 decorator是在类初始化的时候被调用的,而不是在类实例化的时候调用的。
7.2.2 如果调用decorator的时候指定的参数,那么__call__会立刻被调用,并且__call__必须返回一个函数,这个函数会在对应的实例方法时被调用的时候被调用。
7.2.3 如果调用decorator的时候没有指定参数,那么Python会把decorator对应的方法作为参数传给decorator的构造函数,并且__call__不会立即被调用,只有当对应的方法被调用的时候__call__才会被调用
8. 接下来看一个自定义函数作为decorator的例子:
def HelloDecorator(func): print '+++++++++++HelloDecorator:',func def call(*args): print '+++++++++++HelloDecorator.call:',args return func(*args) return call def GoodbyeDecorator(abc): print '+++++++++++GoodbyeDecorator,',abc def call(func): print '+++++++++++GoodbyeDecorator.call:',func return func return call class A(object): @HelloDecorator def SayHello(self,person): print 'hello,',person @GoodbyeDecorator('abc') def SayGoodbye(self, person): print 'goodbye,',person print '+++++++++++++++++++++' listener = A() print '----------------------' listener.SayHello('world'); listener.SayGoodbye('world');
8.1 运行后得到下面的打印输出:
+++++++++++HelloDecorator: <function SayHello at 0x0254D530> +++++++++++GoodbyeDecorator, abc +++++++++++GoodbyeDecorator.call: <function SayGoodbye at 0x0254D5F0> +++++++++++++++++++++ ---------------------- +++++++++++HelloDecorator.call: (<__main__.A object at 0x0254A7F0>, 'world') hello, world goodbye, world
8.2 总结一下:
自定义函数作为decorator的作用和自定义类作为decorator相似,
不同之处是,不指定参数的函数型decorator的call在被调用时会有对应的类的对象作为参数传进来,
所以从这点上来讲,在无参数情况时,就用自定义函数作为decorator
9. Decorator在高级语言,如C#,Java中被大量使用,Decorator也是Python的一个重要功能,使用得当可以简化编程,所以掌握它的使用方法是很有必要的。
10. 参考资料
http://legacy.python.org/dev/peps/pep-0318/
http://www.oschina.net/translate/decorators-and-functional-python