Python中的纯位置参数

106 阅读2分钟

在函数定义中使用/ 标记指定纯位置参数的能力是即将发布的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

下面的情况将适用。

  • / 左边的所有参数(在这个例子中,xy )只能以位置传递。
  • 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中提出了仅有位置的参数,值得看一下该文档以更详细地了解该功能。