上一篇说完了装饰器的原理,现在新的需求来了,我们需要对有/不定长参数的函数进行装饰,那么我们需要怎么对我们的装饰器进行改造呢?
读者你想别着急,如果是你的话,你会怎么做呢?
一:对带参数的函数进行装饰
def func(functionName):
def inner(a, b):
functionName(a, b)
return inner
@func
def demo(a, b):
print("a = %s, b = %s" % (a, b))
demo(1, 2)
打印的结果为 a = 1, b = 2
如果只对demo函数传入参数,会报TypeError: funcin() takes 0 positional arguments but 2 were given的错误,意思inner函数不需要参数,但是却给了两个参数
二:对不定长参数的传递
现在我们的需求又增加了,新添加一个函数demo1。但是demo1需要传入三个参数,那么我们又该怎么去修改呢?难道要在写一个装饰器?
答案当然是 不存在的!
def func(functionName):
def funcin(*args, **kwargs):
functionName(*args, **kwargs)
return funcin
@func
def demo(a, b):
print("a = %s, b = %s" % (a, b))
demo(1, 2)
@func
def demo1(a, b, c):
print("a = %d, b = %d c = %d" % (a, b, c))
demo1(3, 4, 5)
解决方法就是 解包!
OK,到此为止,从第一篇装饰器对无参数的函数装饰,这篇是带多个参数的函数进行装饰和对不定长参数参数的装饰都已经说完了。
三:对有返回值的函数进行装饰
def func(functionName):
def funcin(*args, **kwargs):
res = functionName(*args, **kwargs)
return res
return funcin
@func
def demo(a, b):
print("a = %d, b = %d" % (a, b))
return "我是返回值"
result = demo(1, 2)
print(result)
打印的结果
a = 1, b = 2
我是返回值
需要注意的是当有返回值的时候,在闭包函数中的functionName()函数需要一个变量来接收,并且需要返回
如果在闭包函数中没有定义接收的变量和返回值,那么就会在打印的时候就会出现None
当我们调用demo()的时候实际上是调用了funic() 而当执行到了functionName()的时候实际上是调用了demo的函数体
在demo函数体中有一个返回值return ,但是在functionName并没有变量接收,所以返回None
四:带参数的装饰器
def func_arg(arg):
def func(functionName):
def func_in():
print("hello--%s" % arg)
functionName()
return func_in
return func
# 1.先执行func_arg("test")函数,这个函数return的结果是func这个函数的引用
# 2.@func
# 3.使用@func对demo进行装饰
@func_arg("test")
def demo():
print("world")
demo()
打印结果
hello--test
world
带有参数的装饰器,能够起到在运行时,有不同的功能。