*args 和 **kwargs

这两个都是 Python 中函数参数中的语法,分别代表着 可变长度的参数关键字变量参数,对于大多数静态类型(或者编译型)的程序语言来说,函数(方法)的参数个数和类型都是确定的,例如下面这个 C 函数的原型:

int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);

参数格式固定为 3 个,然后每个参数的类型是固定的。

那么对于这种静态类型的函数,我们如果预先不知道传递的参数个数,或者说因为各种原因传递的个数是不确定的,那么一般的解决方式是怎样的?还是以 C 语言为例,介绍一下通用的方法:

int select(int maxfd1, fd_set *readset, fd_set *writeset, fd_set *exceptset, 
           const struct timeval *timeout);

这里的处理方式就是传递数组(变量指针),但是有一点需要注意的是同时也传递了数组成员的个数,但有些程序语言默认支持获取数组对象的长度的也不用传递长度。但是,总的来说就是传递数组来达到不定数量参数的目的。但是,这个方式有一个缺点就是我们只能传递同样类型的参数,因为数组里面的元素的类型都是一样的,如果我们需要变动一下也是可以的,例如:

int test(void *ary);

在 C 程序我们可以通过 void * 这个指针类型来适应不同的参数类型,但是这又限制了我们必须知道每个位置上的变量类型。

可变长度的参数

我们可以看到,在静态类型语言中,对于参数的类型和数量,都是限制比较大的,但是,在 Python 中的话,我们就比较宽松了,除了和静态语言中一样的严格数量限制的普通函数:

def test(a, b):
    pass

我们还可以通过 可变长度的参数 让我们的函数接受不定长度的参数(C语言也接受不定参数,但是缺点如上),例如

def test(a, b, *args):
    pass

test(1, 2)
test(1, 2, 3)
test(1, 2, 3, 4)

这样的话我们对于参数的可操作性就更多了,而且值得一提的是参数的类型也是比较宽松的,args 的类型不用一致,使用的时候也很方便,就当做数组一样使用。

关键字变量参数

我们知道,在 Python 中,我们除了默认的参数之外,还支持关键字参数,也就是说我们可以在传参的时候指定参数的名字和值,例如:

callme(name="zhangsan")

但是,我们也知道,要想使用这个变量,我们在定义函数的时候需要定义这个变量的名字,例如:

def callme(name="default"):
    pass

可变长度参数 一样,我们可能希望在定义的时候不预设那么多变量,希望能在运行时动态的添加,为此 Python 也支持 关键字变量参数,这样的话,我们就可以不预先定义名字,而是在使用的时候指定了:

def test(**kwargs):
    if "name" in kwargs:
        print("{}={}".format("name", kwargs["name"])

test(name="zhangsan")
>> name=zhangsan
test()
>>
>>

这就是一个简单的 关键字变量参数 的例子,我们可以将参数当做一个字典参数来使用,除此之外,没有其他太大区别。

Reference

· EOF ·

最近爬虫很是凶猛,标注下文章的原文地址: https://liuliqiang.info/post/args-and-kwargs-in%20python/