赞
踩
一、装饰器
装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼。装饰器的功能,就是在运行代码原来功能基础上,加上一些其它功能,比如权限的验证,比如日志的记录等等。不修改原来的代码,进行功能的扩展,使代码的功能更强大。比如java中的动态代理,python的注解装饰器。
写代码要遵循开放封闭原则(OCP),虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
· 封闭:已实现的功能代码块
· 开放:对扩展开发
假设已经写好的某段代码如下,该代码的功能就是增加一个用户,只需调用函数即可运行:
运行结果不用多说,自然是成功的增加一个用户:
但若是此时上级要求你,让你把对该段代码的操作记录制作成日志,你肯定会这么做:
在这里用到的@record就是一个装饰器。为了更好的展示,我们把日志内容print以下,以便看效果。在这里装饰器作用为:在一个函数上方添加了装饰器,如@record,会改变函数代码的运行顺序,装饰器可以引导代码运行直至达到我们想要的效果。以上的例子中,用户在操作时与之前一样只是调用了addUser()函数,在函数即将运行时检测到上方有一个装饰器,此时将会先运行装饰器同名的函数体,在该函数内我们可以写任意需要的代码,原来的函数addUser()的名称addUser将作为参数,传给装饰器函数。在装饰器函数内部嵌套一个函数,以便将原来的代码addUser()函数重新调用,然后返回内部函数的地址,形成闭包(闭包主要是为了解决被装饰函数的参数传递问题,后面会介绍)。这样就使得我们增加日志的需求得以满足,并且不影响原来函数的运行,也不会对用户产生影响。
如果某函数上面有多个装饰器,此时函数运行时先运行离函数最近的装饰器对应的函数,依次往上运行。请看下面的例子:
#定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
#定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makeBold
def test1():
return "hello world-1"
@makeItalic
def test2():
return "hello world-2"
@makeBold
@makeItalic
def test3():
return "hello world-3"
print(test1()))
print(test2()))
print(test3()))
运行结果:
<b>hello world-1</b>
<i>hello world-2</i>
<b><i>hello world-3</i></b>
1. 引入日志
2. 函数执行时间统计
3. 执行函数前预备处理
4. 执行函数后清理功能
5. 权限校验等场景
6. 异常的处理
7. 缓存
三、 装饰器(decorator)的示例
1.为无参函数装饰,上面已经作为例子介绍过了,简单看一下图例:
运行结果:
2.为有参函数装饰,即需要装饰的函数带有参数,此时可以在装饰器对应的函数中的内部函数传参:
运行结果:
3.被装饰函数有不定长参数,用万能参数 *args,**kwargs:
运行结果:
4.装饰器中的return
5.类装饰器
装饰器函数其实是这样一个接口约束,它必须接受一个callable(可调用)对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。若是某个类的对象重写(overide)了 __call__() 方法,那么这个对象就是callable的。
先定一个人的类,然后为其实例化一个对象:
File "D:/Project/lianxi/__fibonacci.py", line 14, in <module>
p1()
TypeError: 'Person' object is not callable 也就是说p1不是一个可以被调用的对象。但若是在类内部重写(overide)__call__()方法后,当前类的所有对象都可以被调用,并且在调用时默认调起__call__()方法。
也就是说,通过在类内部重写(overide)__call__()方法,我们可以直接调起当前类的对象,并调起__call__()方法,我们可以通过在__call__()方法内部增加函数,如验证登录、记录日志等,这就是类装饰器。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。