Kivy A to Z -- Python Decorator的使用

来源:互联网 发布:nginx clientbodytemp 编辑:程序博客网 时间:2024/04/29 03:12

 

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 funcclass A(object):    @HelloDecorator    def SayHello(person):        print 'hello,',person    @GoodbyeDecorator('abc')    def SayGoodbye(self, person):        print 'goodbye,',personprint '+++++++++++++++++++++'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, worldgoodbye, 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 calldef GoodbyeDecorator(abc):    print '+++++++++++GoodbyeDecorator,',abc    def call(func):        print '+++++++++++GoodbyeDecorator.call:',func        return func    return callclass A(object):    @HelloDecorator    def SayHello(self,person):        print 'hello,',person    @GoodbyeDecorator('abc')    def SayGoodbye(self, person):        print 'goodbye,',personprint '+++++++++++++++++++++'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, worldgoodbye, 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

 

 

1 0