在函数定义中使用/ 标记指定纯位置参数的能力是即将发布的3.8版本中Python语言的许多新改进之一。这种语法的增加具有性能上的优势,并且可以实现更好的 API 设计。让我们看看纯位置参数背后的动机以及如何使用它,并举例说明。
背景介绍
在Python中,只有关键字的参数可以使用* 标记,而为只有位置的参数添加/ 标记可以提高语言的一致性。对于位置参数或关键字参数,混合的调用约定并不总是可取的。考虑一下这些例子。
- 一些函数参数已经具有语义。
namedtuple(typenames, field_names, …) - 参数名称没有真正的外部意义。
arg1,arg2, ..., 等为min()
如果用户开始使用关键字参数,库的作者不能重新命名参数,因为这将是一个破坏性的改变。在min() 的情况下,参数的名字没有提供内在的价值,迫使作者永远保持它的名字,因为调用者可能会把参数作为一个关键词来传递。这个问题通过仅有位置的参数来解决。此外,解析和处理纯位置参数的速度也更快。
如何使用只带位置的参数
要指定参数为只带位置的,应该在函数定义中所有这些参数后面添加一个/ 标记。以此为例。
def pow(x, y, /, mod=None):
r = x ** y
if mod is not None:
r %= mod
return r
下面的情况将适用。
/左边的所有参数(在这个例子中,x和y)只能以位置传递。mod可以以位置方式传递,也可以用关键字传递。
>>> pow(2, 10) # valid
>>> pow(2, 10, 17) # valid
>>> pow(2, 10, mod=17) # valid
>>> pow(x=2, y=10) # invalid, will raise a TypeError
>>> pow(2, y=10) # invalid, will raise a TypeError
另一个例子。
def table_format(items, separator=',', /, prettify=False):
pass
- 一旦一个仅有位置的参数被指定为默认值,下面的仅有位置的参数和有位置或关键字的参数也需要有默认值(在这个例子中,
prettify)。 - 没有默认值的仅有位置的参数是
required仅有位置的参数(在这种情况下,items)。
通用情况
一个函数定义,包括所有类型的参数传递变体,看起来是这样的。
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only
什么时候使用只带位置的参数
- 如果名字不重要或者没有意义,而且只有几个参数总是以相同的顺序传递,那么就使用纯位置参数。
- 当名字有意义,并且通过明确的名字使函数定义更容易理解时,使用关键字。
在PEP570中提出了仅有位置的参数,值得看一下该文档以更详细地了解该功能。