Python装饰器如何传入**kwargs作为参数及相关报错解决
错误原因分析
- 核心问题是变量作用域混淆:你调用
@deco(3,4,like="andrew")时传入的like参数,是被外层deco函数的**kwargs接收的,属于deco的作用域变量。而你内层longer函数定义里的**kwargs,是用来接收被装饰函数greet调用时传入的参数,两个kwargs完全是不同作用域下的独立变量,你在longer里取当前调用参数的kwargs['like'],但你调用greet('r')时没有传like参数,自然抛出KeyError。 - 你尝试的第二种写法
def deco(x,y,'like'):本身存在语法错误,Python函数的形参不能是字符串字面量。 - 你尝试的第一种写法
def deco(x,y,like):语法本身是合法的,报错原因还是和最开始的问题一样,没有正确取用deco层拿到的like参数。
修复方案
只需要把deco层拿到的like参数直接在longer里引用即可,不需要从longer的调用参数里取,修改后的代码如下:
import time import math def deco(x,y,*args,**kwargs): # 先把deco层拿到的like参数存下来,避免和内层变量命名冲突 deco_like = kwargs.get('like') def short(func): # 内层的参数换个命名更不容易混淆 def longer(r,*args,**call_kwargs): print("before func exe") begin = time.time() func(r) end = time.time() print("after func exe") # 直接引用deco层拿到的参数 print("I am ", deco_like) print("Total time taken in : ", func.__name__, end - begin) return longer return short @deco(3,4,like="andrew") def greet(r): r = "I will be selelcted" print(r) print(greet('r'))
如果你希望like是deco的必填关键字参数,也可以直接把deco的参数定义改成def deco(x,y,*, like):,星号表示后面的参数必须用关键字传参,调用方式还是和之前一致。
内容的提问来源于stack exchange,提问作者shaila
相关产品推荐
相关产品推荐

