一、基本概念

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


def (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之前。

二、位置参数

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

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
3print_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传进来,这样函数就可以定义为:


def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum

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

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

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

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,要调用一个可变位置参数怎么办?可以这么做:


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

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


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

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


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#")

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


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:

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

2name = python

value = 5

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

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

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


def normal_func(arg1, arg2, arg3):
print("arg1: " + arg1)
print("arg2: " + arg2)
print("arg3: " + arg3)
normal_func("python", 1, 3)

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


# 使用*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
3arg1: python
arg2: 1
arg3: 3