Kivy A to Z -- Python Decorator的使用

 

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

 

 

你可能感兴趣的:(android,python,kivy)