PEP 3102 – 仅限关键字参数
- 作者:
- Talin <viridia at gmail.com>
- 状态:
- 最终
- 类型:
- 标准跟踪
- 创建:
- 2006 年 4 月 22 日
- Python 版本:
- 3.0
- 历史记录:
- 2006 年 4 月 28 日,2006 年 5 月 19 日
摘要
本 PEP 提出更改函数参数分配给命名参数槽的方式。特别是,它使声明“仅限关键字”参数成为可能:这些参数只能通过关键字提供,并且永远不会被位置参数自动填充。
基本原理
当前的 Python 函数调用范式允许通过位置或关键字指定参数。参数可以通过名称显式填充,也可以通过位置隐式填充。
在许多情况下,函数需要接受可变数量的参数。Python 语言使用“varargs”语法 (*name
) 支持这一点,该语法指定任何“剩余”参数都将作为元组传递到 varargs 参数中。
当前,这方面的局限性在于,所有常规参数槽都必须先填充,才能填充 vararg 槽。
这并不总是可取的。可以轻松地想象一个接受可变数量的参数,但也接受一个或多个“选项”作为关键字参数的函数。当前,唯一的方法是定义一个 varargs 参数和一个“keywords”参数 (**kwargs
),然后手动从字典中提取所需的关键字。
规范
从语法上来说,拟议的更改相当简单。第一个更改是允许常规参数出现在 varargs 参数之后。
def sortwords(*wordlist, case_sensitive=False):
...
此函数接受任意数量的位置参数,以及一个名为“case_sensitive”的关键字选项。该选项永远不会被位置参数填充,但必须通过名称显式指定。
仅限关键字参数不需要具有默认值。由于 Python 要求所有参数都绑定到值,并且由于绑定到仅限关键字参数的值的唯一方式是通过关键字,因此这些参数是“必需关键字”参数。这些参数必须由调用方提供,并且必须通过关键字提供。
第二个语法更改是允许省略 varargs 参数的 Argument name。这意味着允许为那些本来不接受 varargs 参数的函数提供仅限关键字参数。
def compare(a, b, *, key=None):
...
此更改背后的原因如下。想象一下一个接受多个位置参数以及一个关键字参数的函数。
def compare(a, b, key=None):
...
现在,假设您想让“key”成为仅限关键字的参数。在上述语法下,您可以通过在关键字参数之前添加 varargs 参数来实现这一点。
def compare(a, b, *ignore, key=None):
...
不幸的是,“ignore”参数还会吸收调用方可能提供的任何错误的位置参数。鉴于我们希望任何不需要的参数都引发错误,我们可以这样做。
def compare(a, b, *ignore, key=None):
if ignore: # If ignore is not empty
raise TypeError
作为一个方便的快捷方式,我们可以简单地省略“ignore”名称,这意味着“不允许任何位置参数超出此点”。
(注意:在对替代语法提案进行大量讨论之后,BDFL 已表示支持此“单星”语法来指示位置参数的结束。)
函数调用行为
上一节描述了旧行为和新行为之间的差异。但是,拥有一个独立描述新行为也很有用,而无需参考以前的模型。因此,下一节将尝试提供这样的描述。
调用函数时,输入参数按如下方式分配给形式参数
- 对于每个形式参数,都有一个槽用于保存分配给该参数的 Argument value。
- 已分配值的槽标记为“已填充”。尚未分配值的槽被视为“空”。
- 最初,所有槽都标记为“空”。
- 位置参数首先分配,然后是关键字参数。
- 对于每个位置参数
- 尝试将 Argument 绑定到第一个未填充的参数槽。如果该槽不是 vararg 槽,则将其标记为“已填充”。
- 如果下一个未填充的槽是 vararg 槽,并且它没有名称,则这是一个错误。
- 否则,如果下一个未填充的槽是 vararg 槽,则所有剩余的非关键字 Argument 都将放入 vararg 槽中。
- 对于每个关键字参数
- 如果存在与关键字名称相同的参数,则 Argument value 将分配给该参数槽。但是,如果参数槽已填充,则这是一个错误。
- 否则,如果存在“关键字字典”参数,则使用关键字名称作为字典键将 Argument 添加到字典中,除非已经存在具有该键的条目,在这种情况下这是一个错误。
- 否则,如果没有关键字字典,也没有匹配的命名参数,则这是一个错误。
- 最后
- 如果 vararg 槽尚未填充,则将空元组分配为其值。
- 对于每个剩余的空槽:如果该槽具有默认值,则用默认值填充该槽。如果没有默认值,则这是一个错误。
根据当前的 Python 实现,遇到的任何错误都将通过引发 TypeError
来发出信号。(如果您想要其他东西,那就是另一个 PEP 的主题。)
向后兼容性
本 PEP 中指定的函数调用行为是现有行为的超集 - 也就是说,预期任何现有程序都将继续工作。
版权
本文件已置于公有领域。
来源:https://github.com/python/peps/blob/main/peps/pep-3102.rst
最后修改时间:2023 年 9 月 9 日 17:39:29 GMT