PEP 457 – 仅限位置参数的表示法
- 作者:
- Larry Hastings <larry at hastings.org>
- 讨论至:
- Python-Dev 列表
- 状态:
- 最终版
- 类型:
- 信息性
- 创建日期:
- 2013年10月8日
概述
本 PEP 提出了 Python 中仅限位置参数的表示法。仅限位置参数是没有外部可用名称的参数;当调用接受仅限位置参数的函数时,位置参数仅根据其位置映射到这些参数。
本 PEP 是一个信息性 PEP,描述了在描述使用仅限位置参数的 API(例如在 Argument Clinic 中,或在 inspect.Signature 对象的字符串表示中)时使用的表示法。另一个 PEP,PEP 570,提议将此表示法提升为完整的 Python 语法。
基本原理
Python 始终支持仅限位置参数。Python 的早期版本缺乏按名称指定参数的概念,所以自然所有参数都是仅限位置的。这种情况在大约 Python 1.0 左右发生了变化,当时所有参数突然变成了位置或关键字参数。但是,即使在当前版本的 Python 中,许多 CPython 的“内置”函数仍然只接受仅限位置参数。
用现代 Python 实现的函数可以通过可变参数 *args 参数接受任意数量的仅限位置参数。但是,没有 Python 语法来指定接受特定数量的仅限位置参数。换句话说,有许多内置函数的签名无法用 Python 语法表示。
本 PEP 提出了一种用于此类签名的表示法,它可以构成向后兼容语法的基础,该语法应该允许在纯 Python 代码中实现任何内置函数(有关该提案,请参阅PEP 570)。
当前 Python 中仅限位置参数的语义
有许多内置函数只接受仅限位置参数。由此产生的语义对于 Python 程序员来说很容易体验到——只需尝试调用其中一个,并通过名称指定其参数即可。
>>> pow(x=5, y=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: pow() takes no keyword arguments
此外,还有一些函数具有特别有趣的语义。
range(),它接受一个在其所需参数*左侧*的可选参数。[2]dict(),其映射/迭代器参数是可选的,并且在语义上必须是仅限位置的。此参数的任何外部可见名称都会遮蔽该名称进入**kwarg关键字可变参数字典![1]
显然,可以通过接受 (*args, **kwargs) 并手动解析参数,在纯 Python 代码中模拟其中任何一个。但这会导致 Python 函数的签名与其实际接受的参数之间出现脱节,更不用说实现所述参数解析的工作了。
动机
本 PEP 不建议我们在 Python 中实现仅限位置参数。本 PEP 的目标只是定义语法,以便
- 文档可以清晰、明确、一致地表达函数的参数将如何解释。
- 该语法保留供将来使用,以防社区某天决定将仅限位置参数添加到语言中。
- Argument Clinic 可以使用该语法的一种变体作为其输入的一部分,用于定义内置函数的参数。
仅限位置参数文档的现状
仅限位置参数的文档不完整且不一致。
还有一个重要的想法需要考虑:目前在文档中无法判断函数是否接受仅限位置参数。open() 接受关键字参数,ord() 不接受,但仅仅通过阅读文档无法判断这是真的。
语法和语义
从“万米高空”来看,暂时忽略 *args 和 **kwargs,函数定义的语法目前看起来像这样。
def name(positional_or_keyword_parameters, *, keyword_only_parameters):
基于这种观点,函数的新语法将如下所示。
def name(positional_only_parameters, /, positional_or_keyword_parameters,
*, keyword_only_parameters):
/ 之前的所有参数都是仅限位置的。如果函数签名中未指定 /,则该函数不接受任何仅限位置参数。
仅限位置参数可以有默认值,如果有默认值,则它们是可选的。没有默认值的仅限位置参数是“必需”的仅限位置参数。
仅限位置参数的更多语义
- 尽管仅限位置参数在技术上具有名称,但这些名称仅供内部使用;仅限位置参数*绝不能*通过名称进行外部寻址。(类似于
*args和**kwargs。) - 如果
/之后有参数,则必须在/之后指定一个逗号,就像在表示转换为仅限关键字参数的*之后有一个逗号一样。 - 此语法对
*args或**kwargs没有影响。
其他限制
Argument Clinic 使用这种语法的一种形式来指定内置函数。它施加了理论上不必要但使实现更容易的进一步限制。具体来说:
- 具有仅限位置参数的函数目前不能具有任何其他类型的参数。(这在不久的将来可能会稍微放宽。)
- Argument Clinic 支持一种称为“可选组”的附加语法。“可选组”是一组顺序的仅限位置参数,它们必须作为一个组被指定或不被指定。例如,如果在 Argument Clinic 中定义了一个接受四个参数的函数,并且所有参数都是仅限位置的并且属于一个可选组,那么在调用函数时必须指定零个参数或四个参数。这对于覆盖更多的 Python 遗留库是必要的,但超出了本 PEP 的范围,不建议实际包含在 Python 语言中。
未来实现者的注意事项
如果我们决定在未来版本的 Python 中实现仅限位置参数,我们将不得不做一些额外的工作来保留它们的语义。问题是:当函数被调用时,我们如何通知参数没有为其传递任何值?
显而易见的解决方案是:向 Python 添加一个新的单例常量,当参数未映射到参数时传递该常量。我建议将该值命名为 undefined,并将其作为名为 Undefined 的特殊类的单例。如果仅限位置参数在调用时未接收到参数,则其值将设置为 undefined。
但这又引出了一个问题。我们如何区分“此仅限位置参数未接收到参数”和“调用者为此参数传入了 undefined”?
禁止将 undefined 作为参数传递给函数(例如,引发异常)会很好。但这会降低 Python 的速度,而且“同意的成年人”规则在这里似乎适用。因此,禁止它可能应该受到强烈劝阻,但不应完全阻止。
但是,应该允许(并鼓励)用户函数将 undefined 指定为参数的默认值。
未解决的问题
Python 中有三种类型的参数:
- 仅限位置参数,
- 位置或关键字参数,以及
- 仅限关键字参数。
Python 允许函数同时具有 2 和 3。而一些内置函数(例如 range)同时具有 1 和 3。那么同时具有 1 和 2 的函数有意义吗?或者以上所有类型?
致谢
将“/”用作仅限位置参数和位置或关键字参数之间分隔符的功劳归于 Guido van Rossum,这是他 2012 年的一项提案。[6]
将左侧选项组赋予更高优先级的功劳归于 Alyssa Coghlan。(2013 年在美国 PyCon 上的面对面交流。)
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0457.rst
最后修改时间:2025-02-01 08:59:27 GMT