python装饰器

原文: http://www.klipdas.com/blog/?p=python-decorator

python装饰器介绍

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

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