Python装饰器知识点补充
首先回顾一下关于Python装饰器以及装饰器模式
补全
根据Java实现装饰器模式的,我们可以写下面一段代码:
importlogging defuse_logging(func): logging.warn("%sisrunning"%func.__name__) returnfunc deffoo(): print('iamfoo') foo=use_logging(foo) foo()#调用
这个实现对于上篇文章中提到的Java使用装饰器。上面也是一个装饰器,实现最简单的一个增加函数日志的功能,但是如果这个额外功能是要去检测传入的参数时,这时上面的就不行了。这时12步轻松搞定python装饰器中的例子还是精妙的。
#装饰器 defwrapper(func): defchecker(a,b):#1 ifa.x<0ora.y<0: a=Coordinate(a.xifa.x>0else0,a.yifa.y>0else0) ifb.x<0orb.y<0: b=Coordinate(b.xifb.x>0else0,b.yifb.y>0else0) ret=func(a,b) ifret.x<0orret.y<0: ret=Coordinate(ret.xifret.x>0else0,ret.yifret.y>0else0) returnret returnchecker #原函数 defadd(a,b): returnCoordinate(a.x+b.x,a.y+b.y) #使用装饰 add=wrapper(add)
细心你会发现,装饰器函数的参数就是传入的原函数,而内部函数的参数跟原函数一模一样,最外层返回的是内部函数的引用,内部函数返回的是传入参数的引用调用的结果
这里用到了函数作为参数特性,当然还有些闭包的知识,具体请看上面提到的博客链接,真的讲的不错。
而上篇说到的Python装饰特性就是这个神奇的语法糖了,可以这样使用
#原函数 @wrapper defadd(a,b): returnCoordinate(a.x+b.x,a.y+b.y)
带参数的装饰器
如果要实现一个带参数的装饰器,那要怎么写呢
deftime_diff(s): defdecorator(func): defwrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) end_time=time.time() print("[%s]执行程序所用时间:%s"%(s,end_time-start_time)) returnres returnwrapper returndecorator @time_diff("polynomial_1") defpolynomial_1(n,x): res=0 foriinrange(n): res+=i*pow(x,i) returnres
调用并执行输出结果:
print(polynomial_1(1,5)) [duoxiangshi_1]执行程序所用时间:4.76837158203125e-06 0
带参数的装饰器需要在不带参数装饰器外再定义一层函数,最外层函数的返回值是第二层函数的引用。
总结:多些多练,用于实际中,才能更加熟练。最近学数据结构与算法,写些装饰器用来看程序执行时间,真是再方便不过了!