Python 2.2中引入的 classmethod() 和 staticmethod() 内置函数,你可以这样调用classmethod():
class A: def foo(self, y): print y foo = classmethod(foo)
也可以这样:
class A: @classmethod def foo(self, y): print y
虽然classmethod是内置函数,但它和普通的函数没有两样,因此你也可以创建自己的函数转化逻辑,如:
def mydecorator(func): print 'mydecorator was called.' func.name = 'myfun' return func
该修饰器将稍微修改了原函数的逻辑:首先打印一段文字“mydecorator was called.”,然后给原函数添加了一个name属性,属性值为"myfun",之后再将函数放回,使用方法和调用结果如下:
class A: @mydecorator def foo(self, y): print y if __name__ == '__main__': a = A() a.foo(1)
运行结果为:
mydecorator was called. 1
以上简介我们可以大致了解了python装饰器的作用。
如上一节的示例中我们发现,使用装饰器的时候是@mydecorator,或者是foo=mydecorator(foo),而不是@mydecorator(),或者foo=mydecorator(foo)()。显然,我们要的装饰器是个函数,而不是函数的结果。因为我们要将我们要修饰的函数foo(即老函数)传递给修饰函数mydecorator,并且修饰函数mydecorator也返回一个新函数(上一的新函数是在老函数的基础上添加了一个属性)。
上一节的介绍装饰器的调用过程,我们可以明白,@mydecorator是个函数,而且是个函数就可以,实际上是必须要实现__call__方法的对象就可以了。也就是说装饰器可以定义成实现了__call__方法的class也可以是其他的任何返回函数的“对象”,后者实现较复杂,但功能强大。
实现__call__方法的class示例:
class mydecorator: def __init__(self, func): self.func = func def __call__(self): print “mydecorator was called.” return self.func
使用方法同前面的示例一样,因为我们可以像函数一样调用该类:mydecorator(),不同的是,该类是以被装饰的函数作为构造参数,而不是作为__call__的参数。更复杂的装饰器:
def mydecorator(arg): print “arg is ”, arg def newdec(func): print ‘new decorator was called.’ def replacedec(self): print ‘replace decorator was called.self.count=’,self.count return func(self) return replacedec return newdec
使用示例:
class A2: def __init__(self): self.count = -1 @mydecorator('yes') def method(self): print self.count if __name__ == '__main__': a = A2() a.method()
输出结果:
Args is yes new decorator was called. decorator was called. self.count=-1 -1
要注意的是replacedec函数,可以看出该函数有一个参数self,该参数就是method的self参数,即A2对象。可以进一步总结出,装饰器的调用过程,对装饰器嵌套函数的解释:首先将”yes”参数传递装饰器mydecorator,然后将被装饰的函数作为参数传递给newdec嵌套函数,然后将被装饰的函数的参数做为参数传递给下一层嵌套的函数replacedec。如图:
多个参数的示例:
def mydecorator(arg1, arg2): print "level 1 : Arg1=%s, arg2=%s" % (arg1, arg2) def newdec(func): print 'level 2 : newdec was called. the arg is func=%s' % func def replace(self, x, y): print "level 3 : replace was called. self is %s, x=%s, y=%s" % (str(self), str(x), str(y)) return func(self, x, y) return replace return newdec class A2: def __init__(self): pass @mydecorator('Hello', 'word.') def method(self, x, y): print x, y if __name__ == '__main__': a = A2() a.method(1, 2)运行结果为:
level 1 : Arg1=Hello, arg2=word. level 2 : newdec was called. the arg is func=<function method at 0x04A06130> level 3 : replace was called. self is <__main__.A2 instance at 0x04A05850>, x=1, y=2 1 2