深入学习Python中的装饰器使用
|
装饰器 vs 装饰器模式 宏的历史 宏的目标 能用Python装饰器做些什么 @entryExit def func1(): print "inside func1()" @entryExit def func2(): print "inside func2()" 函数的装饰器 @myDecorator def aFunction(): print "inside aFunction" 当编译器走到这段代码的时候,函数aFunction会被编译,编译得到的函数对象会传递给myDecorator,装饰器会生成一个新的函数对象来替换原有的函数aFunction。
class myDecorator(object):
def __init__(self,f):
print "inside myDecorator.__init__()"
f() # Prove that function definition has completed
def __call__(self):
print "inside myDecorator.__call__()"
@myDecorator
def aFunction():
print "inside aFunction()"
print "Finished decorating aFunction()"
aFunction()
当你执行这段代码的时候,你会看到这样的输出: inside myDecorator.__init__() inside aFunction() Finished decorating aFunction() inside myDecorator.__call__() 请注意,myDecorator的构造器实际是在装饰函数的时候执行的。我们可以在__init__()里面调用函数f,能够看到,在装饰器被调用之前,函数调用f()就已经完成了。另外,装饰器的构造器能够接收被装饰的方法。一般来讲,我们会捕捉到这个函数对象然后接下来在函数__call__()里面调用。装饰和调用是两个非常清晰明了的不同的步骤,这也是我为什么说类似装饰器更简单同时也更强大的原因。 def foo(): pass foo = staticmethod(foo) 因为有了@这个装饰器操作符, 你可以非常优雅的得到同样的结果: @staticmethod def foo(): pass 不过也有不少人因为这一点反对装饰器,不过@仅仅是一个很小的语法糖而已,把一个函数对象传递给另外一个函数,然后用返回值替换原有的方法。 青出于蓝
class entryExit(object):
def __init__(self,f):
self.f = f
def __call__(self):
print "Entering",self.f.__name__
self.f()
print "Exited",self.f.__name__
@entryExit
def func1():
print "inside func1()"
@entryExit
def func2():
print "inside func2()"
func1()
func2()
运行结果是: Entering func1 inside func1() Exited func1 Entering func2 inside func2() Exited func2 现在我们能够看到,那些被装饰的方法有了“进入”和“离开”的跟踪信息。 使用函数作为装饰器
def entryExit(f):
def new_f():
print "Entering",f.__name__
f()
print "Exited",f.__name__
return new_f
@entryExit
def func1():
print "inside func1()"
@entryExit
def func2():
print "inside func2()"
func1()
func2()
print func1.__name__
def entryExit(f):
def new_f():
print "Entering",f.__name__
new_f.__name__ = f.__name__
return new_f
你可以动态的获取函数的信息包括那些你做的更改,这在python里面非常有用。 带参数的装饰器
class decoratorWithArguments(object):
def __init__(self,arg1,arg2,arg3):
"""
If there are decorator arguments,the function
to be decorated is not passed to the constructor!
"""
print "Inside __init__()"
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
def __call__(self,f):
"""
If there are decorator arguments,__call__() is only called
once,as part of the decoration process! You can only give
it a single argument,which is the function object.
"""
print "Inside __call__()"
def wrapped_f(*args):
print "Inside wrapped_f()"
print "Decorator arguments:",self.arg1,self.arg2,self.arg3
f(*args)
print "After f(*args)"
return wrapped_f
@decoratorWithArguments("hello","world",42)
def sayHello(a1,a2,a3,a4):
print 'sayHello arguments:',a1,a4
print "After decoration"
print "Preparing to call sayHello()"
sayHello("say","hello","argument","list")
print "after first sayHello() call"
sayHello("a","different","set of","arguments")
print "after second sayHello() call"
从输出结果来看,运行的效果发生了明显的变化: Inside __init__() Inside __call__() After decoration Preparing to call sayHello() Inside wrapped_f() Decorator arguments: hello world 42 sayHello arguments: say hello argument list After f(*args) after first sayHello() call Inside wrapped_f() Decorator arguments: hello world 42 sayHello arguments: a different set of arguments After f(*args) after second sayHello() call (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
