Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 211 – 添加一个新的外积运算符

作者:
Greg Wilson <gvwilson at ddj.com>
状态:
已拒绝
类型:
标准跟踪
创建日期:
2000年7月15日
Python 版本:
2.1
发布历史:


目录

Warning

本 PEP 已被拒绝。

×

后续 PEP 465 中的方法最终被接受,取代了本 PEP。该 PEP 的“拒绝的替代方案”更详细地解释了其理由。

引言

本 PEP 描述了一项提案,旨在将 @(发音为“across”)定义为 Python 2.2 中的一个新的外积运算符。当应用于序列(或其他可迭代对象)时,此运算符将组合它们的迭代器,因此

for (i, j) in S @ T:
    pass

将等价于

for i in S:
    for j in T:
        pass

类将能够使用特殊方法 __across____racross____iacross__ 重载此运算符。特别是,新的 Numeric 模块(PEP 209)将为多维数组重载此运算符以实现矩阵乘法。

背景

数值计算现在只是计算的一小部分,但许多程序员——包括许多 Python 用户——仍然需要用代码表达复杂的数学运算。大多数数值语言,如 APL、Fortran-90、MATLAB、IDL 和 Mathematica,因此提供了两种形式的常见算术运算符。一种形式逐元素工作,例如将矩阵参数的对应元素相乘。另一种实现了该操作的“数学”定义,例如执行行-列矩阵乘法。

Zhu 和 Lielens 提出以这种方式使 Python 的运算符加倍。他们的提案将创建六个新的二元中缀运算符和六个新的原地运算符。

此提案的最初版本更为保守。作者咨询了 GNU Octave [1](MATLAB 的开源克隆)的开发者。其开发者同意提供一个用于矩阵乘法的中缀运算符很重要:数值程序员确实关心他们是必须写 mmul(A,B) 而不是 A op B

另一方面,当被问及拥有用于矩阵求解和其他操作的中缀运算符有多重要时,James Rawlings 教授回答说 [2]

我**不**认为这是必须的,我做了很多矩阵求逆。我不记得是 A\b 还是 b\A,所以我总是写 inv(A)*b。我建议放弃 \

基于这次讨论,以及来自美国国家实验室和其他地方的学生的反馈,我们建议只向 Python 添加一个新的运算符,用于矩阵乘法。

迭代器

Python 2.2 计划添加迭代器,这为本提案开辟了更广阔的范围。作为 PEP 201(同步迭代)讨论的一部分,本提案的作者进行了一项非正式可用性实验 [3]。结果表明,用户在心理上接受“交叉积”循环语法。例如,大多数用户预期

S = [10, 20, 30]
T = [1, 2, 3]
for x in S; y in T:
    print x+y,

会打印 11 12 13 21 22 23 31 32 33。我们相信用户对

for (x, y) in S @ T:
    print x+y

也会有同样的反应,即他们会自然地将其解释为编写嵌套循环的简洁方式。

这就是迭代器发挥作用的地方。在执行循环之前实际构建两个(或更多)序列的交叉积会非常昂贵。另一方面,@ 可以定义为获取其参数的迭代器,然后创建一个外部迭代器,该迭代器返回内部迭代器返回的值的元组。

讨论

  1. 添加一个名为“across”的函数对 Python 的影响将小于一个新的中缀运算符。然而,这不会让 Python 对数值程序员更具吸引力,他们确实关心他们是否可以使用运算符编写矩阵乘法,或者是否必须将其编写为函数调用。
  2. @ 应该以与比较运算符相同的方式可链式使用,即
    (1, 2) @ (3, 4) @ (5, 6)
    

    必须返回 (1, 3, 5) ... (2, 4, 6),而**不是** ((1, 3), 5) ... ((2, 4), 6)。这不应该需要解析器的特殊支持,因为第一个 @ 创建的外部迭代器可以很容易地被教导如何与普通迭代器组合。

  3. 必须有某种方法来区分可重新启动的迭代器和不可重新启动的迭代器。例如,如果 S 是输入流(例如文件),L 是列表,那么 S @ L 是直接的,但 L @ S 则不然,因为流的迭代不能重复。这可以被视为错误,或者通过让外部迭代器检测不可重新启动的内部迭代器并缓存它们的值来处理。
  4. 在三位 Python 初学者(都是经验丰富的程序员)面前对该提案进行白板测试表明,用户将期望
    "ab" @ "cd"
    

    返回四个字符串,而不是四个字符对的元组。对于

    ("a", "b") @ "cd"
    

    应该返回什么,意见不一……

备选方案

  1. 什么也不做——保持 Python 简单。

    这始终是默认选择。

  2. 添加一个命名函数而不是运算符。

    Python 主要不是一种数值语言;为了这种特殊情况而使其复杂化可能不值得。然而,对真实矩阵乘法的支持**确实**经常被请求,并且为内置序列类型提出的 @ 语义将简化非常常见的惯用法(嵌套循环)的表达。

  3. 引入所有现有运算符的前缀形式,例如 ~*~+,如 PEP 225 中所提议的。

    我们对此的反对意见是,没有足够的需求来证明额外的复杂性(参见 Rawlings 的评论 [2]),并且提议的语法未能通过“低墨粉”可读性测试。

致谢

我感谢朱怀宇发起这次讨论,并感谢 James Rawlings 和各种 Python 课程的学生就数值程序员真正关心的问题进行的讨论。

参考资料


来源:https://github.com/python/peps/blob/main/peps/pep-0211.rst

最后修改:2024-04-14 20:08:31 GMT