Python 函数的位置参数(positional argument)和关键字参数(keyword argument)
在 Python 里,函数的参数默认是 positional-or-keyword
,就是说即可以是位置参数,也可以是关键字参数。文档里是这样描述的:
positional-or-keyword: specifies an argument that can be passed either positionally or as a keyword argument. This is the default kind of parameter ..
比如:
>>> def f(a, b, c):
... print('a={}, b={}, c={}'.format(a, b, c))
...
>>> f(1, 2, 3)
a=1, b=2, c=3
>>> f(a=1, c=3, b=2)
a=1, b=2, c=3
>>> f(1, c=3, b=2)
a=1, b=2, c=3
函数调用的时候,可以按位置参数直接调用,比如 f(1, 2, 3)
,也可以按(部分或者全部的)关键字参数调用,比如 f(1, c=3, b=2)
,这里顺序都可以随意指定,因为在理解上不存在歧义。
在其他语言里,参数类型和位置是需要明确的,至于参数名字,其实并不重要。但在 Python 里,既然可以是关键字参数,那参数名字就是属于函数定义的一部分。如果更改了函数参数的名字,那么已经实现的调用了这个函数的代码里,凡是用到关键字参数来调用的地方,都要相应地修改。
在 Python 3.8 里引入了这样的语法:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
在这个函数里 :
- 参数 a、b 是位置参数(positional-only);
- 参数 c、d 可以是位置参数,也可以是关键字参数;
- 参数 e、f 只能是关键字参数(keyword-only);
有了这样的语法后,函数在使用时会比较直接,跟其他语言里一致,比如文档里举的一个例子:
def divmod(a, b, /):
"Emulate the built in divmod() function"
return (a // b, a % b)
这里 a、b 只能按位置参数来使用,而不能用作关键字参数。那这种位置参数,参数名字就不再是函数的一部分了,以后即使参数名字修改了,已有代码也不用跟着调整,从而避免了关键字参数引入的问题。
再比如:
>>> help(len)
Help on built-in function len in module builtins:
len(obj, /)
Return the number of items in a container.
>>>
>>> len(obj=range(10))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: len() takes no keyword arguments
>>>
>>> len(range(10))
10
>>>
这里也一样,obj 不能作为关键字参数来用。
参考资料