前面使用的都是位置参数,因为它们的位置至关重要。本节介绍的技巧让你能完全的忽略位置。要熟悉这种技巧需要一段时间,但随着程序规模的增大,你很快就发现它很有用。
>>> def hello_1(greeting,name):
... print('{},{}'.format(greeting,name))
...
>>> def hello_2(name,greeting):
... print("{},{}".format(name,greeting))
...
这俩个函数的功能完全相同,只是参数的排列顺序相反。
>>> hello_1('hello','world')
hello,world
>>> hello_2('hello','world')
hello,world
有时候,参数的排列顺序可能难以记住,尤其是参数很多时。为了简化调用工作,可指定参数的名称。
>>> hello_1(greeting='hello',name='world')
hello,world
在这里,参数的顺序无关紧要。不过参数名称很重要。
像这样使用名称指定的参数称为关键字参数,主要的有点是有助于澄清各个参数的作用。
然而,关键字参数的最大的优点在于,可以指定默认值。
>>> def hello_3(greeting='hello',name='world'):
... print('{},{}!'.format(greeting,name))
像这样给参数指定默认值后,调用函数时可不提供它!可以根据需要,一个参数也不提供,提供部分参数值或提供全部参数值。
>>> hello_3()
hello,world!
>>> hello_3('greeting')
greeting,world!
>>> hello_3('greeting','universe')
greeting,universe!
如你所见,仅使用位置参数就很好,只不过如果要提供参数name,必须同时提供参数greeting。如果指向提供参数name,并让参数greeting使用默认值呢?相信你已经猜到该怎么做了。
>>> hello_3(name='gumby')
hello,gumby!
你可结合使用位置参数和关键字参数,但必须先指定所有的位置参数,否则解释器将不知道它们是哪个参数。
请尝试使用下面这样的函数定义
>>> def print_patam(*params):
... print(params)
这里好像只指定了一个参数,但它前面有一个星号。这是什么意思呢?尝试使用一个参数来调用这个函数,看看结果如何。
>>> print_patam('sdadasd')
('sdadasd',)
>>>
注意到打印的是一个元组,因为里面有一个逗号。
参数前面的星号将提供的所有值放入一个元组中,也就是讲这些值收集起来。这样的行为以前我们见过,赋值时星号的变量收集多余的值。不过它是将收集的值存放在列表中而不是元组中,除此以外,这俩种用法很像。下面编写一个函数:
>>> def print_pata(title,*params):
... print(title)
... print(params)
并尝试调用它
>>> print_pata("param:",1,2,3)
param:
(1, 2, 3)
因此星号意味着收集余下的位置参数。如果没有可供收集的参数,params将是一个空元组。
>>> print_pata("nothing:")
nothing:
()
与赋值时一样,带星号的参数也可以放在其他位置(而不是最后),但不同的是,在这种情况下你需要做额外的工作;使用名称来指定后续参数。
>>> in_the_middle(1,2,3,4,5,z=7)
1 (2, 3, 4, 5) 7
>>> in_the_middle(1,2,3,4,5,7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: in_the_middle() missing 1 required keyword-only argument: 'z'
星号不会收集关键字参数
>>> def print_patam(*params):
... print(params)
>>> print_patam(s=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print_patam() got an unexpected keyword argument 's'
要收集关键字参数,可使用俩个星号。
>>> print_param(x=1,y=2,z=3)
{'x': 1, 'y': 2, 'z': 3}
如你所见,这样得到的是一个字典而不是元组。
如下个复杂的结合例子:
>>> def print_param_4(x,y,z=3,*pospar,**keypar):
... print(x,y,z)
... print(pospar)
... print(keypar)
...
>>> print_param_4(1,2,3,4,5,6,7,foo=1,bar=2)
1 2 3
(4, 5, 6, 7)
{'foo': 1, 'bar': 2}
>>> print_param_4(1,2)
1 2 3
()
{}
我们可以看到结果,keypar吸收了后俩个关键字参数形成了字典,x,y,z分别占了前三个参数,剩余由pospar以元组的方式的吸收。当参数只有俩个的时候由于z有默认值,所以前三个为1,2,3后俩个都是空,一个是空元组,一个空字典。