Python装饰器
前言
在上一节的讲解,介绍了有关闭包和装饰器的简单介绍,并且了解了装饰器的形式,这节开始介绍一些装饰器的示例,更好的理解装饰器。
一、对无参数的函数进行装饰
这是最简单的一种装饰器,被装饰的函数即没有返回值也没有参数,例程如下所示:
def decorate(func):
def in_decorate():
print("过来装饰!")
func()
return in_decorate
@decorate
def test():
print("ei,能装我就不装,就是玩儿~")
test()
# OUT = 过来装饰!
# OUT = ei,能装我就不装,就是玩儿~
二、对有定长参数的函数进行装饰
如果被装饰的函数有了参数,在装饰的时候就要引入参数,其做法也很简单,只要在装饰器最内部的函数填入和被装饰函数相同个数的参数就可。
解释是,因为在执行@decorate时,其本质上相当于执行了decorate = deocorate(func), 此时上述执行的结果指向in_decorate的函数引用,所以,我们在调用in_decorate时,把参数传入就可以在in_decorate的内部使用func(a),即完成了对带有参数的函数进行装饰的效果。
def decorate(func):
def in_decorate(a):
print("过来装饰!")
func(a)
return in_decorate
@decorate
def test(a):
print("%s,能装我就不装,就是玩儿~" % a)
test("qi")
# OUT = 过来装饰!
# OUT = qi,能装我就不装,就是玩儿~
三、对有不定长参数的函数进行装饰
与定长参数的装饰相似,对于不定长参数的装饰也是在装饰器函数的最内部函数里传入不定长参数,然后再通过函数调用。但是,需要注意的部分是,在对不定长参数的函数进行装饰时,在调用func()的时候,参数也需要加上与**,即args与**kwargs,此时的操作是拆包,如果不写的话,args是一整个元组,而kwargs则是一整个字典传入。
不定长参数的拆包:
def test(*args, **kwargs):
print("args", args)
print("*args", *args)
print("kwargs", kwargs)
test(1, 2, 3, a=1, b=2, c=3)
# OUT = args (1, 2, 3)
# OUT = *args 1 2 3
# OUT = kwargs {'a': 1, 'b': 2, 'c': 3}
对有不定长参数的函数进行装饰:
def decorate(func):
def in_decorate(*args, **kwargs):
print("过来装饰!")
func(*args, **kwargs)
return in_decorate
@decorate
def test(a, b, c):
print("%s,%s,%s" % (a, b, c))
test("qi", "来啊", "谁怕谁")
# OUT = 过来装饰!
# OUT = qi,来啊,谁怕谁
四、对有return的函数进行装饰
对于含有return的函数进行装饰的方式,就在in_decorate()内,return 回去即可。
def decorate(func):
def in_decorate(*args, **kwargs):
print("过来装饰!")
return func(*args, **kwargs)
return in_decorate
@decorate
def test(a, b, c):
return "%s,%s,%s" % (a, b, c)
ret = test("qi", "来啊", "谁怕谁")
print(ret)
# OUT = 过来装饰!
# OUT = qi,来啊,谁怕谁
五、装饰器带参数
所谓的装饰器带参数,即使装饰器在上面的条件上能接收外部变量。学过闭包我们就知道如果想使装饰器能接收外部变量,在当前装饰器函数的基础上再套一层函数用于接收参数即可。
def decorate(par="ei"):
def in_decorate(func):
def in_in_decorate(*args, **kwargs):
print("过来装饰!")
return func(par, *args, **kwargs)
return in_in_decorate
return in_decorate
@decorate("ei")
def test(a, b, c):
return "%s,%s,%s" % (a, b, c)
ret = test("来啊", "谁怕谁")
print(ret)
# OUT = 过来装饰!
# OUT = ei,来啊,谁怕谁
六、类装饰器
装饰器函数本质上就是其需要接收一个callable对象作为参数,然后返回一个callable对象。Python中,一般的callable对象都是函数,但也有例外。只要某个对象重写了 call() 方法,那么这个对象就是callable的。
class Test(object):
def __init__(self, func):
self.func = func
def __call__(self):
print("过来装饰")
return self.func()
@Test
def test():
print("ei,就不装,就是玩儿~")
test()
# OUT = 过来装饰
# OUT = ei,就不装,就是玩儿~
总结
本节介绍了在工作中我们会遇到的相关装饰器。
在后面的自己写一个web框架中会用到我们学过的知识。