• 导致Python之父不干了的PEP 572讨论
  • 发布于 2个月前
  • 271 热度
    0 评论

“PEP 572一团糟”是2018年Python语言峰会的主题,该峰会由永远仁慈的独裁者Guido van Rossum领导。PEP 572试图将赋值表达式(或“内联赋值”)添加到该语言中,但在python开发邮件列表上的多个大议程上,甚至在多次讨论python思想之后,都进行了长时间的讨论。这些议程常常是有争议的,而且显然数量很多,以至于许多人可能就把它们关闭了。在峰会上,Van Rossum概述了这个特性建议,他似乎倾向于接受这个建议,但是他也想讨论如何避免将来出现这种议程激增的情况。


赋值
Van Rossum表示,他将努力总结他认为这场争议的全部内容,不过他警告称:“或许我们会发现,这是另外一回事。”PEP背后的基本思想是在表达式中执行赋值,这将使编写一些代码结构变得更容易。C语言有这个特性,Go也有,但后者使用了一些额外的语法,他觉得这些语法令人讨厌。
C语言风格的赋值问题使它会导致这个经典错误:
  if (x = 0)
       ...
这在语法上是合法的,但可能不是程序员想要的,因为它将0赋值给x(而不是测试它是否等于0),而且在if之后的语句块从不会执行。Van Rossum说,如果您不认为这是一个真正的问题,那么可以看看yoda风格的条件表达式(原文: Yoda-style conditions),这些条件表达式颠倒了条件的顺序,如果使用=而不是==,那么它将导致语法错误(如果这个问题不重要,Yoda风格为什么要这样规定?):
   if (0 = x)
       ...
Python发誓要以一种不同的方式解决这个问题。正如Tim Peters最近提醒他的那样,最初的Python只有一个“=”用于赋值和等式测试,但是它使用了不同的语法区别来确保不会出现C语言那样的问题。Python总是“自豪”自己没有任何可能产生这个错误赋值问题,也不必求助于像Yoda风格这样的技巧。
在模式匹配中,这类赋值非常有用的一个经典例子是:
 m = re.match(p1, line)
    if m:
        return m.group(1)
    else:
        m = re.match(p2, line)
        if m:
            return m.group(2)
        else:
            m = re.match(p3, line)
            ...
PEP中提出的语法将使用一个新的“:=”操作符(可以将其理解为“变成”),这样一系列类似于上面的匹配可以替换为:
 if m := re.match(p1, line):
        return m.group(1)
    elif m := re.match(p2, line):
        return m.group(2)
    elif m := re.match(p3, line):
        ...
另一种激励代码模式是“半循环”。以前,按行处理文件是很常见的,但现在已经通过使文件对象具有可迭代性解决了这一问题;然而,其他不可迭代的接口仍然受到如下模式的困扰:
 line = f.readline()
    while line:
        ...  # process line
	line = f.readline()
或者像这样:
 while True:
        line = f.readline()
	if not line:
	    break
	... # process line
这两种方法都可以用一个更清晰简洁的版本来取代,那就是使用一个赋值表达式:
    while line := f.readline():
        ... # process line
Van Rossum说他知道自己已经写过很多半循环的代码,而且有时没有写对。赋值表达式清楚地表达了作者的意图,而其他两个表达式则使代码的读者更加难以了解是怎么回事。
另一个例子是列表解析(如列表、字典)。有时程序员为了解析的简洁性,以至于会两次调用一个昂贵的函数。他见过这种事情,甚至在优秀程序员的代码中也见过。

但是Python在没有这个功能的28年里做得非常好。人们对这个想法的反应各不相同。人们希望找到来自真实代码的示例,而不是为了证明PEP的合理性而生成的玩具示例。Van Rossum说,Peters和其他人从他们自己的代码中找到了现实的例子,在这些例子中,这个特性可以使代码更短,更重要的是,使代码更清晰。然而,所有这些例子都太长,不适合放在他的幻灯片上。


有争议的辩论
他认为,争论如此激烈的原因之一是,人们提出了许多不同的语法变化。以下是议程中讨论的可能性部分列表:
 NAME := expr
    expr -> NAME
    NAME <- expr
    expr {NAME}
    NAME = expr
    expr2 where NAME = expr1
    let NAME = expr1 in expr2
    ...
可以看到,一些使用了新的操作符,另一些使用了关键字,等等。Van Rossum说,他曾试图推动c风格的赋值,看看它能走多远,但其他人正在推动他们自己的变体。除此之外,还讨论了一些不同的意见,包括需要括号、运算符的不同优先级、允许目标不是一个简单名称(例如obj.attr或者a[i]),并将构造限制为if、elif和while。

另一个有争议的问题是在早期混合到PEP中的子-局部作用域的概念。其思想是,隐式作用域只在语句执行期间有效;它可能很有用,但也有一些奇怪的地方。最后,它从PEP中被去掉了。
他说,总的来说,这个想法一直“极具争议”。一些人认为可读性更好,另一些人认为可读性更差。好处是适度的,每个人都有自己喜欢的语法。子-局部作用域添加了其他奇怪的地方,并且需要新的字节码来实现它。
PEP还附带了另一个问题的修复,这个问题在类作用域的理解中是一个“奇怪的角落事件”。他说,这应该从PEP 572中移除,并转换为它自己的PEP。
在PEP 572上进行了一次投票,但是附加的角落-事件修复是PEP的一部分。这让投票变得混乱,因为那些想要赋值功能但又不想(或不确定)包含补丁的人没有办法投票,需要进行一次新的投票。PEP也过早地转移到python-dev。
Van Rossum说,Python不是民主团体。但一般人都同意他的决定,“除非我不接受(他们)最喜欢的改变”。

Mark Shannon想知道Python教育大会的与会者是否对这个特性有一些想法。Van Rossum承认一些人说这个特性使得教授Python变得更加困难,但是他并不确定,部分原因是他不知道人们是如何学习Python的。Nick Coghlan说该问题是试图描述=和:=之间的区别,但是Van Rossum建议老师不要在教学代码中使用:=。然而,他确实认识到,像Stack Overflow这样的站点会导致一些新手以可能令人困惑或错误的方式复制代码。


决策
Van Rossum说,这个PEP的更大问题是“我们如何做出决定”。议程中有许多长响应,主要针对该特性。总的来说,“电子邮件太多了”。有许多误解、离题、解释,既有对的,也有错的,等等。部分问题在于,没有真正的方法来衡量新语言特性的有效性。

最后,他不得不停止阅读这些帖子,以免自己“发疯”。Chris Angelico是PEP的作者,他不可能出现在峰会上,但是Van Rossum建议他停止在议程中回应,试图把事情压下来。他想知道如何从这种情况中“找出一条出路”。人们开始创建新议程是为了引起那些用太多消息压制旧议程者的注意。


Łukasz Langa建议“独裁者决定”; Van Rossum或许应该利用他的角色来阻止这类事情的发生。但如果不这样,Van Rossum可能就只能像他那样,推迟并停止关注那些议程。Langa说,正是出于这个原因,他从来没有遵循过Python的思想。Van Rossum说,在将它加入到python-dev之前,在python思想讨论的基础上对PEP已经进行了四次修订;他认为“我们做得对”。Langa想知道是否还有其他类似反应的PEP。静态类型(也称为“类型提示”)就是Van Rossum记得的一种。Shannon认为核心开发人员发布的负面帖子没有PEP 572那么多。Van Rossum同意这一点,但他也记得几个核心开发人员也反对输入提示。

Victor Stinner建议在PEP中总结关于python思想的讨论。Van Rossum说,他认为许多回复的人根本没有读过PEP中的讨论部分。他注意到关于python思想的讨论比关于python开发的讨论要好,尽管它也有很多充满激情的帖子。遵循Python思想的人越来越少,Christian Heimes说。Van Rossum想知道,反对派是不是在他介入之后才变得激烈起来的;人们可能没有认真对待这件事,因为他们认为他不会为了这个而去。


Ned Deily建议用峰会讨论的模式来限制讨论持续的时间;也许在做出决定前五天。Tcl项目的流程要正式得多,核心开发人员需要对提案进行投票,但他不知道Python项目是否想要这样做。Van Rossum说,找个人来管理对于PEPs的对话可能会起作用。他熟悉上世纪90年代末的IETF流程,其中有一些就是这样。他实际上是从IETF借鉴来建立PEP流程的。

但是Barry Warsaw认为PEP 572是一个离群者。由于它改变了语言的语法,人们往往只关注语法,而不理解更深层次的语义问题。他建议,也许除了PEP作者之外,还有一个小团队可以指导这一类PEP。但最终,人们还是会继续讨论它,直到有人以这样或那样的方式做出关于PEP的声明。


Van Rossum说他通常是避免冲突的,他不喜欢仅仅使用他的BDFL权力来结束一场讨论。Angelico在写这种类型的PEPs方面有些生疏; Van Rossum认为,如果Angelico和Peters没有参与讨论,他很可能就不会一直坚持推动它。Steve Dower说,也许可以将一些PEP发送回去,并请求其他人员与作者合作。


Brett Cannon指出PEP编辑器在转向python-dev之前并没有特别仔细地检查PEP,而主要是确保没有出现大的文本问题。有一个工作组来确保PEP在进行质量讨论时处于正确状态,这可能会有帮助。Van Rossum说,另一个想法是找一位关于PEPs特性的资深合著者。除了是PEP主题方面的专家,他们还可以利用自己的权威来帮助引导讨论。
用户评论