Python中*args和**kwargs的用法总结

Python中*args和**kwargs的用法总结

一、基本概念

Python支持可变参数,最简单的方法莫过于使用默认参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def test_defargs(one, two=2): # 参数one没有默认值,two的默认值为2
print('Required argument:', one)
print('Optional argument:', two)

test_defargs(1)
'''
Required argument: 1
Optional argument: 2
'''

test_defargs(1, 3)
'''
Required argument: 1
Optional argument: 3
'''

另一种达到可变参数(Variable Argument)的方法:

使用*args**kwargs语法。

*args是可变的位置参数(postional arguments)列表;

**kwargs是可变的关键词参数(keyword arguments)列表;

并且规定位置参数必须位于关键词参数之前,即*args必须位于**kwargs之前

二、位置参数

以下是用位置参数正确调用函数的实例:

1
2
3
4
5
6
7
8
9
10
def print_hello(name, sex):
sex_dict = {1: '先生', 2: '女士'}
print('Hello %s %s, welcome to Python World!' % (name, sex_dict.get(sex, '先生'))) # if no such a key, print '先生'

print_hello('Chen', 2) # 位置参数要求先后顺序,对应name和sex
print_hello('Chen', 3) # 两个参数的顺序必须一一对应,且少一个参数都不可以
'''
Hello Chen 女士, welcome to Python World!
Hello Chen 先生, welcome to Python World!
'''

三、关键字参数

用于函数调用,通过“键-值”形式加以指定。

使用关键字参数可以让函数更加清晰,容易使用,同时也清除了参数的顺序需求。

以下是用关键字参数正确调用函数的实例:

1
2
3
print_hello('Chen', sex=1) # 有位置参数时,位置参数必须在关键字参数的前面
# print_hello(1, name='Chen') # Python 3.x中这种写法是错误的
print_hello(name='Chen', sex=1) # 关键字参数之间不存在先后顺序的,等价于print_hello(sex=1, name='Chen')

以下是错误的调用方式:

1
2
# print_hello(name='Chen', 1) # 有位置参数时,位置参数必须在关键字参数前面
# print_hello(sex=1, 'Chen')

四、可变参数

顾名思义,可变参数就是传入的参数个数是可变的,可以是任意个。*args**kwargs两者都是Python中的可变参数。

1.可变位置参数*args

Python中规定参数前带*的,称为可变位置参数,只是我们通常称这个可变位置参数为*args而已,叫其他的也是一样的。

以数学题为例,给定一组数字a,b,c……,请计算a^2 + b^2 + c^2 + ……。

要定义这个函数,必须确定输入的参数。由于参数个数不确定,我们可以首先想到把a,b,c……作为一个list或者tuple传进来,这样函数就可以定义为:

1
2
3
4
5
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum

但是调用的时候,需要先组装出一个list或tuple:

1
2
3
4
>>> calc([1, 2, 3])
14
>>> calc([1, 3, 5, 7])
84

所以,为了方便起见我们把函数的参数改为可变位置函数:

1
2
3
4
5
def calc(*numbers) # 可变位置参数
sum = 0
for n in numbers:
sum = sum + n * n
return sum

定义可变位置参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:

1
2
3
4
>>>calc(1,2)
5
>>>calc()
0

如果已经有一个list或tuple,要调用一个可变位置参数怎么办?可以这么做:

1
2
3
>>>nums = [1, 2, 3]
>>>calc(nums[0], nums[1], nums[2])
14

这种做法当然是可行的,问题是太繁琐了,所以Python允许在list或tuple前面加一个*,把list或tuple的元素变成可变位置参数传进去:

1
2
3
>>>nums = [1, 2, 3]
>>>calc(*nums)
14

总而言之,*args用来表示函数接收可变长度的非关键字参数列表作为函数的输入。我们可以通过以下这个例子进一步理解*args:

1
2
3
4
5
6
def test_args(normal_arg, *args):
print('first normal arg:' + normal_arg)
for arg in args:
print('another arg through *args:' + arg)

test_args("normal", "python", "java", "C#")

上面代码的执行结果如下:

1
2
3
4
first normal arg: normal
another arg through *args : python
another arg through *args : java
another arg through *args :C#

2.可变关键字参数**kwargs

同理,Python中规定参数前带 的,称为可变关键字参数,通常用kwargs表示。

**kwargs表示函数接收可变长度的关键字参数字典作为函数的输入。当我们需要函数接收带关键字的参数作为输入的时候,应当使用**kwargs。我们可以通过以下的例子进一步理解**kwargs:

1
2
3
4
5
6
7
8
9
def test_kwargs(**kwargs):
if kwargs is not None:
for key, value in kwargs.iteritems():
print("{} = {}".format(key,value))
# Or you can visit kwargs like a dict() object
# for key in kwargs:
# print("{} = {}".format(key, kwargs[key]))

test_kwargs(name="python", value="5")

以上代码的执行效果如下:

1
2
name = python
value = 5

以上例子只是*args**kwargs基本使用的例子。下面再给出一个用*args**kwargs来定义能够接受列表输入和字典输入的函数的例子。

3.使用*args**kwargs来调用函数

比如我们有如下接受普通输入参数的函数:

1
2
3
4
5
6
def normal_func(arg1, arg2, arg3):
print("arg1: " + arg1)
print("arg2: " + arg2)
print("arg3: " + arg3)

normal_func("python", 1, 3)

使用*args**kwargs来调用这个函数的代码如下:

1
2
3
4
5
6
7
# 使用*args
args_list = ("python", 1, 3)
normal_func(*args_list)

# 使用**kwargs
kwargs_dict = {"arg3": 3, "arg1": "python", "arg2": 1}
normal_func(**kwargs_dict)

以上三段代码的输出均为:

1
2
3
arg1: python
arg2: 1
arg3: 3

引用文章:

1.Python中的 *args 和 **kwargs - 简书

2.函数的参数 - 廖雪峰的官方网站

3.python参数传递的*args和**kwargs - 简书