参数匹配模型——Python学习之参数(二)
文章目录
位置参数:从左至右进行匹配
一般情况下,也是我们最常使用的那种方法,通过位置进行匹配,把参数值传递给参数头部的参数名称,匹配顺序从左到右。
例如:
def func(name, father_name):
print("%s's father is %s"%(name, father_name))
func('Xiaowang', 'Laowang')
func('Laowang', 'Xiaowang')
运行结果是:
Xiaowang's father is Laowang
Laowang's father is Xiaowang
关键字参数:通过参数名进行匹配
调用者可以定义哪一个参数接受这个值,通过在调用时使用参数的变量名,即 name=value
这种语法。
例如:
def func(name, father_name):
print("%s's father is %s"%(name, father_name))
func(name='Xiaowang', father_name='Laowang')
func(father_name='Laowang', name='Xiaowang')
运行结果是:
Xiaowang's father is Laowang
Xiaowang's father is Laowang
默认参数:为没有传入值的参数定义参数值
如果调用时传入的值过于少的话,函数能够为参数指定默认值,这里再次使用语法 name=value
.
例如:
def func(name, age=10):
print("%s's age is %d"%(name, age))
func('Wang', 20)
func('Wang') # age使用默认值10
运行结果是:
Wang's age is 20
Wang's age is 10
可变参数:收集任意多于基于位置或关键字的参数
如果参数名称以字符*
开头,则表示收集任意多的额外参数(这个特性常常叫做可变参数)。
例如:
def print_params(*params):
print(params)
这里好像只指定了一个参数,但它前面有一个星号。这是什么意思呢?尝试使用一个参数来调用这个函数,看看结果如何。
>>> print_params('Testing')
>>> ('Testing',)
注意到打印的是一个元组,因为里面有一个逗号。也就是说前面有星号的参数将被放在元组中?咱们再试试。
>>> print_params(1, 2, 3)
(1, 2, 3)
可见,参数前面的星号将提供的所有值都放在一个元组中,也就是将这些值收集起来。
再看一个例子:
def print_params_2(title, *params):
print(title)
print(params)
>>> print_params_2('Params:', 1, 2, 3)
Params:
(1, 2, 3)
因此星号意味着收集余下的位置参数。如果没有可供收集的参数,params将是一个空元组。
>>> print_params_2('Nothing:')
Nothing:
()
带星号的参数也可放在其他位置(而不是最后),但不同的是,在这种情况下你需要做些额外的工作:使用名称来指定后续参数。
>>> def in_the_middle(x, *y, z):
... print(x, y, z)
...
>>> 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'
第9行的keyword-only argument
后文会讲。
星号不会收集关键字参数。
def print_params_2(title, *params):
print(title)
print(params)
>>> print_params_2('Hmm...', something=42)
>>> Traceback (most recent call last):
>>> File "<stdin>", line 1, in <module>
>>> TypeError: print_params_2() got an unexpected keyword argument 'something'
要收集关键字参数,可使用两个星号。
>>> def print_params_3(**params):
... print(params)
...
>>> print_params_3(x=1, y=2, z=3)
{'z': 3, 'x': 1, 'y': 2}
如你所见,这样得到的是一个字典而不是元组。
可变参数解包:传递任意多的基于位置或关键字的参数
调用者能够再使用*
语法将参数集合打散,分成参数。这个*
与在函数头部的*
恰恰相反:在函数头部它意味着收集任意多的参数,而在调用者中意味着参数解包。
例如,我们能够通过一个元组给一个函数传递4个参数。
>>> def func(a, b, c, d):
... print(a, b, c, d)
...
>>> args = (1, 2, 3, 4)
>>> func(*args)
1 2 3 4
类似地,如果在调用函数时,**会以键值对的形式解包一个字典,使其成为关键字参数。
>>> def func(a, b, c, d):
... print(a, b, c, d)
...
>>> args = {'a':2, 'b':4, 'c':6, 'd':8}
>>> func(**args)
2 4 6 8
提示
不要混淆函数头部或函数调用时
*
或者**
的语法:在函数头部它意味着收集任意数量的参数,在函数调用时,它解包任意数量的参数。
Keyword-only参数:参数必须按照名称传递
Python3.0 把函数头部的排序规则通用化了,允许我们指定 keyword-only 参数,即必须只按照关键字传递并且不会由一个位置参数来填充的参数。
从语法上讲, keyword-only 参数编码为命名的参数,出现在参数列表中的 *args 之后,所有这些参数都必须在调用中使用关键字语法来传递。例如,在下面的代码中, a 可能按照名称或者位置来传递,b 收集任何额外的位置参数,并且 c 必须只按照关键字传递:
>>> def kwonly(a, *b, c):
print(a, b, c)
>>> kwonly(1, 2, c=3)
1 (2,) 3
>>> kwonly(a=1, c=3)
1 () 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() missing 1 required keyword-only argument: 'c'
我们也可以在参数列表中使用一个*
字符,来表示一个函数期待跟在*
后面的所有参数都作为关键字参数传递。在下面的例子中,a 可能按照位置或者名称传递,但是 b 和 c 必须按照关键字传递。
>>> def kwonly(a, *, b, c):
print(a, b, c)
>>> kwonly(1, c=3, b=2)
1 2 3
>>> kwonly(c=3, b=2, a=1)
1 2 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() takes 1 positional argument but 3 were given
>>> kwonly(1)
TypeError: kwonly() missing 2 required keyword-only arguments: 'b' and 'c'
仍然可以对 keyword-only 参数使用默认值,即便它们出现在函数头部中的*后面。在下面的例子中,a 可能按照名称或位置传递,而 b 和 c 是可选的,但是如果使用的话必须按照关键字传递。
>>> def kwonly(a, *, b='spam', c='ham'):
print(a, b, c)
>>> kwonly(1)
1 spam ham
>>> kwonly(1, c=3)
1 spam 3
>>> kwonly(a=1)
1 spam ham
>>> kwonly(c=3, b=2, a=1)
1 2 3
>>> kwonly(1, 2)
TypeError: kwonly() takes 1 positional argument but 2 were given
实际上,带有默认值的 keyword-only 参数是可选的,但是,那些没有默认值的 keyword-only 参数真正地变成了函数必须的 keyword-only 参数。咱们再看几个例子:
>>> def kwonly(a, *, b, c='spam'):
print(a, b, c)
>>> kwonly(1, b='eggs')
1 eggs spam
>>> kwonly(1, c='eggs')
TypeError: kwonly() missing 1 required keyword-only argument: 'b'
>>> kwonly(1, 2)
TypeError: kwonly() takes 1 positional argument but 2 were given
>>> def kwonly(a, *, b=1, c, d=2):
print(a, b, c, d)
>>> kwonly(3, c=4)
3 1 4 2
>>> kwonly(3, c=4, b=5)
3 5 4 2
>>> kwonly(3)
TypeError: kwonly() missing 1 required keyword-only argument: 'c'
>>> kwonly(1, 2, 3)
TypeError: kwonly() takes 1 positional argument but 3 were given
相关文章:Python学习之参数(一)
参考资料
《Learning Python,5th Edition》
《Python基础教程》人民邮电出版社,第3版