我们经常在开源的一些Python代码中看到 *args**kwargs 这样函数参数定义, 到底他们是含义? 又如何使用呢?

在回答这个问题前,我们先来介绍下, Python 参数传递的方式.

函数定义中的 *args**kwargs

在Python中,参数总是通过赋值传递的, 俗称值传递, 在默认情况下, 参数是通过其位置进行匹配的, 但是Python也是支持关键字的参数匹配形式的.

按位置进行匹配

这是Python的默认行为,通过其位置进行匹配, 从左到右,必须精确的传递和函数头部参数名一样多的参数。这种方式我们平常用的最多,比如:

def foo(a, b, c):
    print(a, b, c)

foo(1, 2, 3)

按关键字进行匹配

按关键字进行参数匹配,在调用函数的时候,能够更加详尽的定义内容传递的位置。关键字参数允许通过变量名进行匹配,而不是通过位置。

def foo(a, b, c):
    print(a, b, c)

foo(a=1, b=2, c=3)

从调用方式,我们可以看到, 以关键字参数使用时,参数从左至右的顺序已经不重要了.因为参数是通过变量名进行传递的,而不是通过其位置.
这种方式使用起来更直观,代码阅读更加清晰.

当然完全可以将基于位置和基于关键字的参数同时使用,这时,所有基于位置的参数从左至右的顺序匹配头部参数,接着按变量名进行关键字匹配.

def foo(a, b, c):
    print(a, b, c)

foo(1, c=3, b=2)

参数默认值

上述提到了Python 参数的匹配模式, 我们继续介绍下, Python 默认参数. 默认参数允许函数定义可选参数.如果没有传入值的话,在函数运行前,可选参数赋予默认值.

def foo(a, b=2, c=3):
    print(a, b, c)

foo(1)

foo(a=1)

foo(a=1,b=4,c=5)

foo(a=1, c=5)

因为参数 a 我们没有定义默认值,所以参数 a 我们必须赋值, 而我们不给 bc 赋值,则默认将 2 赋给 b, 3 赋给 c.
而当我们三个参数同时赋值时,将不再使用默认值.
而关键字参数允许我们跳过有默认值的参数,比如 foo(a=1, c=5) 我们这里就跳过 b 的赋值, b 被赋予了默认值 2.

好了到这里我们就可以介绍我们关注的 *** 修饰的函数参数了.

***表示任意数量的函数参数收集.

*args

* 是以元组的形式收集不匹配的位置参数, 当函数调用时, python将所有为匹配的位置相关的参数收集到一个元祖中, 并将这个元祖赋值给变量args.

def foo(a, *args):
    print(args)

foo(1,2,3,4)

**kwargs

**仅对关键字生效, ** 将未匹配的关键字转换为字典,并赋值给kwargs.

def foo(a, **kwargs)
    print(kwargs)

foo(a=1, b=2, c=3)

函数调用中的 *args**kwargs

基本上, 我们就介绍清楚了, 函数定义过程的中 ***功能和区别. 相反, 如果我们在函数调用过程使用 *** 意味着什么呢?

*args

我们在调用函数的过程中使用 *args 语法,在这种情况下, 它和函数定义的意义正好相反, 用于解包参数的元祖, 而不是在函数定义环节的创建元祖.

def foo(a, b, c, d):
    print(a, b, c, d)

args = (1, 2, 3, 4)
foo(*args)

**kwargs

同样对于调用过程中的 **kwargs, 会以键/值对的形式解包一个字典.

def foo(a, b, c, d):
    print(a, b, c, d)

kwargs = {'a':1, 'b':2, 'c':3, 'd':4}
foo(**kwargs)

到这里, 我们就介绍完了, *args**kwargs 的功能和使用场景.实际使用过程中,可能会碰到混合使用的情况, 尝试下去吧^_^

def foo(a, b, *args, **kwargs):
    print(a, b, args, kwargs)

args=(2, 3)
kwargs = {'d':4}
foo(1, *args, **kwargs)

参考链接

【腾讯云】境外1核2G服务器低至2折,半价续费券限量免费领取!
https://cloud.tencent.com/act/cps/redirect?redirect=1068&cps_key=e4b50f6c64a4480367f8a8d16fd07c5a&from=console

标签: python, args, kwargs, 位置参数, 关键字参数

添加新评论