[转载]Python Decorator
Decorate是装饰的意思。如果你了解Decorator设计模式,那么就很好理解Python的Decorator。
http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators
Decorator是一个可调用的python object。Decorator可以用来修改funciton, method 或者类的定义。
一个object被传进decotator,然后decorator修改这个object并且返回这个object,最后,这个返回的object绑定到原来的那个object的名字上。
Decorator是一个语法糖(syntactic sugar)
创造Decorator这个语法糖的灵感来源于Java的annotations
@viking_chorus def menu_item(): print("spam") 等价于 def menu_item(): print ("spam") menu_item = viking_chorus(menu_item)
对上面代码的一点说明:上面代码很简答, 就是最基本的decotator的功能。viking_chorus是一个decorator,它修饰一个函数,这个函数的名字叫做menu_item。那么与它等价的代码可以描述为:仍然有一个函数名字叫做menu_item,这个函数是一个可调用的python object,所以我们把它传递给decotator(这里就是viking_chorus),viking_chorus里对这个可调用的object进行操作并且返回一个object,最后把这个返回的object命名为menu_item。由此可见,原来的menu_item已经不见了,与这个名字绑定的可调用python object变成了decorator的返回值。
前面说过,Decorator是装饰者模式。下面就是一个例子:
# decorator的定义,它使得对menu_item的一次调用会调用8次原来的menu_item def viking_chorus(myfunc): def inner_func(*args, **kwargs): for i in range(8): myfunc(*args, **kwargs) return inner_func
对上面代码的一点说明:viking_chorus是一个decorator,如前所说,它接受一个被修饰的callable python object,返回一个python object。这里传进来的python object就是myfunc(它是decorator的参数),返回的python object就是函数内部定义的inner_func。而inner_func调用了传进来的myfunc。这样就达到了修饰被修饰python objectg的目的。不过需要注意的是对原来的python object修饰以后其实是返回了另外一个python object作为修饰的结果。
Decoratr最典型的应用是创建class method或者叫做static method(类似于C++的静态函数),增加function attributes,tracing,设置pre和postcondition以及synchronisation。除此以外, decorator还可以用在很多地方比如tail recursion elimination,memoization甚至improving the writing of decorators.
多个Decorator用在一起可以形成一个修饰链比如:
@invincible @favorite_color("Blue") def black_knight(): pass 等价于 def black_knight(): pass invincible(favorite_color("Blue")(black_knight()))
对上面代码的一点说明:favorite_color是一个函数,它接受一个字符串作为一个参数。这个函数应该返回一个Decorator,这个返回的Decorator被用来修饰black_night,修饰的结果是一个callable python object,这个callable python objecti接着又被invincible修饰。
下面的代码更加清楚的说明这个过程:
def black_knight(): pass blue_decorator = favorite_color("Blue") decorated_by_blue = blue_decorator(black_knight) black_knight = invincible(decorated_by_blue) #注意上面一行,返回值必须被赋给black_knight, # 这样下次你调用black_knight函数的时候才会调用那个被层层修饰过的函数
那么那个favorite_color如何实现呢,前面已经说过了,它是一个函数,它返回一个decorator,我们把这个叫做一个工厂(factory),如下面的代码:
def favorite_color(color): def decorator(func): def wrapper(): print(color) func() return wrapper return decorator
前面说python的decorator和decorator设计模式有点相似,但是还是要区分,decorator设计模式是一种针对静态类型面向对象编程语言的设计模式,该设计模式允许在运行时增加对象的功能。而python的decorator是一种语法糖,是在函数或者类定义的时候使用的。
Python26之前,只有函数可以应用decorator,如果想对类应用可以针对__init__函数使用decorator。
Python26开始,有了类的decorator。
http://blog.genforma.com/2011/07/28/class-decorator-talk/
使用class decorator,你可以检查类的属性,绑定其他操作比如logging,transaction等等。
与class decorator使用一个类作为参数,并且返回一个类。decorator的原理是一样的,作为参数的类被修饰,并且返回一个新的类,新的类被赋予参数类的名字,这样当你再用该名字访问这个类的时候,你就得到被修饰过的那个新的类。
比如下面的decorator为你增加一个类的静态变量
def add_foo_decorator(cls): cls.foo = "foo" return cls
使用上面的class decorator:
@add_foo_decorator class A: pass #注意,这个时候你就可以访问A.foo了。
同样的,class decorator也是语法糖,你可以这样实现同样的功能:
class A: pass A = add_foo_decorator(A)
同样的,class decorator也可以形成一个链,同样的,你也可以用一个接受参数的函数返回一个class decorator并且用这个decorator来修饰类
@cls_decorator @cls_decorator_factory("parameter", 2) class B: pass
实现上面代码中的cls_decorator_factory和实现一个类似的修饰函数的decorator是类似的,这里就不多说了。
原文:http://www.cnblogs.com/dbbs/archive/2012/03/07/2382918.html