python 装饰器(通俗易懂版)
2016-12-20 00:00
211 查看
装饰器
我们知道,在Python中,我们可以像使用变量一样使用函数:函数可以被赋值给其他变量
函数可以被删除
可以在函数里面再定义函数
函数可以作为参数传递给另外一个函数
函数可以作为另一个函数的返回
简而言之,函数就是一个对象。
对一个简单的函数进行装饰
为了更好地理解装饰器,我们先从一个简单的例子开始,假设有下面的函数:2 | return'helloworld' |
2 3 4 | defwrapped(): return"<i>"+func()+"</i>" returnwrapped |
现在,我们就可以不改变
2 3 | >>>hello() '<i>helloworld</i>' |
不过要注意的是,由于我们将
2 | 'wrapped' |
现在,我们梳理一下上面的例子,为了增强原函数
2 3 4 5 6 7 8 9 | defwrapped(): return"<i>"+func()+"</i>" returnwrapped defhello(): return'helloworld' hello=makeitalic(hello) |
一般情况下,我们使用装饰器提供的
2 3 4 5 6 7 8 | defwrapped(): return"<i>"+func()+"</i>" returnwrapped @makeitalic defhello(): return'helloworld' |
装饰器的使用形式
装饰器的一般使用形式如下:2 3 | deffunc(): pass |
2 3 | pass func=decorator(func) |
2 3 4 | @decorator_two deffunc(): pass |
2 3 4 | pass func=decorator_one(decorator_two(func)) |
2 3 | deffunc(): pass |
2 3 4 | pass func=decorator(arg1,arg2)(func) |
对带参数的函数进行装饰
前面的例子中,被装饰的函数2 3 4 5 6 7 8 9 10 11 12 13 | defwrapped(*args,**kwargs): ret=func(*args,**kwargs) return'<i>'+ret+'</i>' returnwrapped @makeitalic defhello(name): return'hello%s'%name @makeitalic defhello2(name1,name2): return'hello%s,%s'%(name1,name2) |
内嵌包装函数的参数传给了
看看使用:
2 3 4 | '<i>hellopython</i>' >>>hello2('python','java') '<i>hellopython,java</i>' |
带参数的装饰器
上面的例子,我们增强了函数2 3 4 5 6 7 8 | defdecorator(func): defwrapped(*args,**kwargs): ret=func(*args,**kwargs) return'<'+tag+'>'+ret+'</'+tag+'>' returnwrapped returndecorator |
2 3 4 5 6 7 8 | @makebold defhello(name): return'hello%s'%name >>>hello('world') '<b>helloworld</b>' |
2 3 | defhello(name): return'hello%s'%name |
多个装饰器
现在,让我们来看看多个装饰器的例子,为了简单起见,下面的例子就不使用带参数的装饰器。2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | defwrapped(): return'<b>'+func()+'</b>' returnwrapped defmakeitalic(func): defwrapped(): return'<i>'+func()+'</i>' returnwrapped @makebold @makeitalic defhello(): return'helloworld' |
2 3 4 | return'helloworld' hello=makebold(makeitalic(hello)) |
2 | '<b><i>helloworld</i></b>' |
基于类的装饰器
前面的装饰器都是一个函数,其实也可以基于类定义装饰器,看下面的例子:2 3 4 5 6 7 8 9 10 11 12 13 | def__init__(self,func): self.func=func def__call__(self,*args,**kwargs): return'<b>'+self.func(*args,**kwargs)+'</b>' @Bold defhello(name): return'hello%s'%name >>>hello('world') '<b>helloworld</b>' |
还可以让类装饰器带参数:
2 3 4 5 6 7 8 9 10 11 12 13 14 | def__init__(self,tag): self.tag=tag def__call__(self,func): defwrapped(*args,**kwargs): return"<{tag}>{res}</{tag}>".format( res=func(*args,**kwargs),tag=self.tag ) returnwrapped @Tag('b') defhello(name): return'hello%s'%name |
装饰器的副作用
前面提到,使用装饰器有一个瑕疵,就是被装饰的函数,它的函数名称已经不是原来的名称了,回到最开始的例子:2 3 4 5 6 7 8 | defwrapped(): return"<i>"+func()+"</i>" returnwrapped @makeitalic defhello(): return'helloworld' |
2 | 'wrapped' |
2 3 4 5 6 7 8 9 10 11 12 13 14 | defmakeitalic(func): @wraps(func)#加上wraps装饰器 defwrapped(): return"<i>"+func()+"</i>" returnwrapped @makeitalic defhello(): return'helloworld' >>>hello.__name__ 'hello' |
小结
本质上,装饰器就是一个返回函数的高阶函数。装饰器可以动态地修改一个类或函数的功能,通过在原有的类或者函数上包裹一层修饰类或修饰函数实现。
事实上,装饰器就是闭包的一种应用,但它比较特别,接收被装饰函数为参数,并返回一个函数,赋给被装饰函数,闭包则没这种限制。
参考资料
相关文章推荐
- python装饰器通俗易懂的解释!
- Python装饰器学习
- Python装饰器学习
- Python中几个挺好用的东西(函数、类、装饰器)
- Python札记 -- 装饰器
- (转)Python装饰器与面向切面编程
- Python深入05 装饰器
- python--装饰器
- 用python装饰器来优化算法
- python 多个装饰器组合应用,实现面向切面之AOP编程
- Python: 使用装饰器“@”取得函数执行时间
- Python装饰器学习
- 巧用Python装饰器 免去调用父类构造函数的麻烦
- python——装饰器例子一个
- 理解Python中的装饰器
- Python中的Decorator(装饰器)模式
- Head First 设计模式——装饰器(Decorator Pattern)——Python实现
- Python装饰器学习(九步入门)
- Python装饰器与面向切面编程
- Python装饰器实例:调用参数合法性验证