目录
位置参数与关键字参数
收集参数(args与*kwargs参数)
分配参数
1. 位置参数与关键字参数
参数的概念都是与函数息息相关的。其中def语句中,位于函数名后面的变量通常称为 形参 ,而调用函数时提供的值称为 实参
。一般情况下不对此进行严格区分。
在了解收集参数前(args与*kwargs参数)要知道位置参数与关键字参数的含义。位置参数就是根据位置,进行实参到形参的值传递匹配。如下:
def hello(greeting, name):
print('{},{}!'.format(greeting, name))
>>>hello('Hello', 'World')
Hello,world!
有时候,参数的排列顺序可能很难记住,尤其是参数很多的时候,为了简化调用工作,可指定参数的 名称 ,即将参数赋予关键字。如下:
def hello(greeting, name):
print('{},{}!'.format(greeting, name))
>>>hello(greeting='Hello', name='World')
Hello,world!
>>>hello(name='World', greeting='Hello')
Hello,world!
此时,参数的顺序无关紧要。像这样使用名称指定的参数称为关键字参数,主要有点是有助于澄清各个参数的作用。及时输入参数多些,每个参数的作用也很明确。另外,参数顺序错了也没关系。然而,关键字参数最大的优点在于,可以指定默认值。
def hello(greeting='Hello', name='World'):
print('{},{}!'.format(greeting, name))
像这样给参数指定默认值后,调用函数是可以不提供它!可以根据需求,一个参数值都不提供、提供部分参数值或者提供全部参数值。
2. 收集参数(args与*kwargs参数)
【 温馨提示 : args 即 arguments 的缩写,参数的意思; kwargs 即 keywords
arguments 的缩写,关键字参数的意思。】
有时候,用户需要提供任意数量的参数。实际上,实现起来并不困难,仅需要像这样定义函数:
def print_params(*arg):
print(arg)
这里好像只指定了一个参数,但它的前面有一个星号。可以尝试调用一下,一探究竟。
>>>print_params('Testing')
('Testing',)
>>>print_params(1, 2, 3)
(1, 2, 3)
不难发现,打印的是一个 元组
。也就是说,前面有星号的参数将被放在元组中,也就是将这些值收集起来。带星号的参数可以放在多个形参的后面(此时它收集其他形参没有收集的值),也可以放在前面或者中间,不过此时会麻烦点,如下:
def in_the_middle(x, *y, z):
print(x, y, z)
>>>in_the_middle(1, 2, 3, 4, 5, 6, z=7)
1 (2, 3, 4, 5, 6) 7
可见,如果带星号形参放在前面或者中间,则它后面的参数则需要使用名称指定,类似关键字参数。
另外,单星号参数(*arg)是不会收集关键字参数的,要收集关键字参数,就要使用两个星号。
def print_params_2(**kwargs):
print(kwargs)
>>>print_params_2(x=1, y=2, z=3)
{'z':3, 'x:1, 'y':2}
可见,这样得到的是一个 字典 而不是元组。 讲这些参数形式结合:
def print_params_3(x, y, z=3, *args, **kwargs):
print(x, y, z)
print(args)
print(kwargs)
>>>print_params_3(1, 2, 3, 4, 5, 6, 7, foo=1, bar=2)
1 2 3
(5, 6, 7)
{'foo':1, 'bar':2}
>>>priint_param_3(1, 2)
1 2 3
()
{}
3. 分配参数
前面介绍了如何将参数收集到元组或者字典中,但使用同样的两个运算符(和*)也可以执行相反的操作,即将参数分配传递给形参,恰好与收集实参传递的参数的操作相反。如下:
def add(x, y):
return x+y
#同时假设存在一个元组,包含两个要加的数
params = (1, 2)
>>>add(*params)
3
这与前面执行的操作差不多是相反的:不是收集参数,而是 分配
参数。这是通过在调用函数(而不是定义函数)时实现的。这猴子那个做法也可以用于参数列表的一部分,条件是这部分位于参数列表末尾。通过使用**可将字典中的值分配给关键字参数。如下:
def hello(greeting='Hello', name='World'):
print('{},{}!'.format(greeting, name))
params = {'name':'Song', 'greeting':'Well met'}
>>>hello(**params)
Well met,Song!
最后,给一个忠告,虽然星号和双星号*,既可以使用在定义函数又可以使用在调用函数时,但非常不建议同时使用。如果同时使用,将值传递元组或者字典。因此还不如不用它们,不用还能省去些许麻烦。
这篇文字,写给对python函数不熟悉的同学,也写给记性不好的自己。