前言
昨天我有发一篇跟python中装饰器相关的一些介绍,在今天我又整理了一些漏掉的功能还有其他人的一些提问,还没看过装饰器基本介绍的可以回去看一下装饰器与闭包的文章喔~
python中的闭包&装饰器 提高程式码品质的神器
如何装饰带有参数的副程式
许多人的副程式都会有其他参数输入,所以在wrapper
函数中应该也要有参数传入,但如果副程式中的参数不同,但要使用同一个装饰器该怎么办呢?这时候我们可以请出万用参数*args,**kwargs
。其实这个万用参数的用法也有许多眉角,但本文只介绍此参数在装饰器的用途。*args
和**kwargs
就是python中用于传递可变数量参数的特殊语法。在wrapper
函数中设定输入的参数为*args
和**kwargs
就可以不管被装饰的函式使用的参数量以及参数名称等。具体用法如下:
from time import timedef timing(func): def wrapper(*args,**kwargs): start=time() result = func(*args,**kwargs) end=time() print(f"used time: {end-start}, result:{result}") return wrapper@timingdef sumfunc(s=100000): for i in range(s): s+=i return ssumfunc(s=100000)# used time: 0.005526542663574219, result:5000050000
我们可以看到,当sumfunc()
中有参数传入后,如果wrapper
没有参数设定的话就会喷error,所以如果要被装饰的副程式有需要传入参数时,请记得在wrapper()
中加入*args,**kwargs
。
使用多个装饰器
如果一个富城是要使用多个装饰器可以吗,当然可以!在使用多个装饰器时要注意的是装饰器的顺序,以下列程式举例:
from time import timedef timing(func): def wrapper(*args,**kwargs): start=time() result = func(*args,**kwargs) end=time() print(f"used time: {end-start}, result:{result}") return wrapperdef printfinish(func): def wrapper(*args,**kwargs): func(*args,**kwargs) print(f"Code finish!") return wrapper@printfinish #后执行此装饰器@timing #先执行此装饰器def sumfunc(s=100000): for i in range(s): s+=i return ssumfunc(s=100000)
上面程式我们加了另一个装饰器式程式执行完后会print出Code finish!的字串,我们可以注意到比较下面的@timing会先被执行,接着再执行@printfinish,也就是说越下面的装饰器会先被执行,上面的装饰器会被后执行。另外一个副程式可以被不限数量的装饰器装饰喔!
在类别中的方法使用装饰器
在类别中我们也会使用许多副程式(在类别中被称为方法),在类别中方法使用装饰器的用途也很简单,在类别外定义装饰器(定义装饰器的程式区块要在定义类别的区块前面),然后正常装饰方法就好了!範例如下:
def printname(func): def wrapper(*args,**kwargs): func(*args,**kwargs) print(f"This function is {func.__name__}") return wrapperclass Myclass: @printname def __init__(self): pass @printname def hi(self): passabc = Myclass()abc.hi()# This function is __init__# This function is hi
结语
昨天的文章有一些不完整的部分,今天再将他补齐,希望各位可以更理解装饰器的用法!
另外我今天有看到其他大大的文章,我认为他比我的详细很多orz,各位也可以去看看他的文章,我会在底下放上连结。也感谢这篇文章让我学到更多。
DAY09-搞懂Python的装饰器