[Python开发笔记] **kwargs 一文理解透彻

134 阅读2分钟

Python *args, **kwargs含义是什么?

  • 处理可变参数
  • *args被打包成 tuple
  • **kwargs被打包成dict

image-20250211213155769


**kwargs表示关键字参数(何为关键字?即 k: v 这种形式)

dd = {'a': 1, 'b': 2}

def print_kwargs(**kwargs):
  print(type(kwargs), kwargs)
  for k, v in kwargs.items():
    print(f"{k}: {v}")

print_kwargs(**dd)

这里的print_kwargs(**{'a': 1, 'b': 2})就相当于print_kwargs(a=1, b=2)。这就好比把字典拆开,直接给 print_kwargs(a=1, b=2) 传入参数。或者,

想象 dd = {'a': 1, 'b': 2} 是一个箱子,里面装着两张纸条,分别是a=1, b=2,用**解包相当于打开箱子把这两张纸条分别递给print_kwargs(), 所以就等于直接写print_kwargs(a=1, b=2)

好了,上面的理解了,那如果是 dd = {'a': 1, 'b': 2, 'c': {'d': 3}}这种形式的想完全最后输出a: 1 b: 2 d:3这样式的完全解包怎么做?

算法有一个核心思想是 递归 试着用这个来解决该问题:

dd = {'a': 1, 'b': 2, 'c': {'d': 3}}

def print_kwargs_recursive(**kwargs):
  for k, v in kwargs.items():
    if instance(v, dict):					# 判断当前元素是否还是字典,是则没解包完全,则继续递归进去
      print_kwargs_recursive(**v)	# 递归关键,注意进去的时候传的 v 需要解包
    else:
      print(f"{k}: {v}"")

print_kwargs(**dd)

输出:

a: 1

b: 2

c: 3

ok,这个理解了之后,那么dd = {'a': 1, 'b': 2, 'c': {'d': 3, 'e': {'f': 4, 'g': 5}}}该怎么处理呢?


最近遇到了一些疑惑,[2025-03-03]

>>> def add(**kwargs):
    return kwargs
>>> add()            # 没有参数,kwargs 为空字典
{}
>>> add(x=1)         # x=1 => kwargs={'x': 1}
{'x': 1}
>>> add(x=1, y=2)    # x=1, y=2 => kwargs={'y': 2, 'x': 1}
{'y': 2, 'x': 1}

和👇

>>> def add(x, y, z):
...     return x + y + z
...
>>> dict1 = {'z': 3, 'x': 1, 'y': 6}
>>> add(dict1['x'], dict1['y'], dict1['z'])    # 这样传参很累赘
10
>>> add(**dict1)        # 使用 **dict1 来传参,等价于上面的做法
10

怎么一会**在函数传参中一会在变量旁边?

**在python中有两种主要用法,一个在函数定义时,一个在函数调用时。

  1. 函数定义时的**kwargs

    def add(**kwargs):
        return kwargs
    
    add(x=1, y=2)  # 调用时使用关键字参数
    # 相当于在函数内部得到:kwargs = {'x': 1, 'y': 2}
    
  2. 函数调用时的**dict

    def add(x, y, z):
        return x + y + z
    
    dict = {'x': 1, 'y': 2, 'z': 3}
    add(**dict)
    

参考文章:

python之旅