注意: 虽然 JavaScript 不是本网站的必要功能,但您的内容交互将受到限制。请启用 JavaScript 以获得完整体验。

PEP 集锦

PEP 集锦

Python10 会议 的开发者日开始时,我做了一个主题演讲,最后是以我称之为“PEP 集锦”的内容结束。这是对 所有开放的 PEP 的简要概述,我对每个 PEP 都给出了我个人且主观的意见。后来,我意识到这可能对其他开发者也有用。我没有在会议上做笔记,所以下面是我在 2002 年 3 月 7 日的两个小时内从头开始创建的一组不同的评论。我打算偶尔用新的评论和新的 PEP 更新此内容。

--Guido van Rossum

PEP 42 - 小型特性请求 - Hylton

坦白地说,这主要是“锦上添花”想法的垃圾场,这些想法没有足够的优先级来实施。似乎没有人会浏览它并找到一个好主意,为之编写代码并提交补丁。所以实际上,一个被移到 PEP 42 的想法比一个被直接拒绝的想法更糟糕——它处于一个僵尸区,既不能升天堂也不能下地狱。我们如何改变这种情况?

PEP 206 - 2.0 自带电池 - Zadka

这是一个好主意。但 PythonLabs 没有精力推进它,原作者也没有。我们如何使之成为社区努力?

PEP 209 - 添加多维数组 - Barrett, Oliphant

2002 年 3 月 28 日: 我之前的评论是基于几个误解。(例如,新 Numeric 中的切片与旧版本中的行为相同,并且不会像我错误地认为的那样进行复制。)引用 Perry Greenfield 的话:

[...] 新版本越来越向后兼容。事实上,仍然存在的主要差异是
  1. 当标量与数组组合时,强制转换规则存在差异。在科学 Python BoF 上,人们一致认为这种改变是一件好事。

  2. 类型由类型对象而不是单个字符代码表示。我们已经实现了这一点,使其向后兼容,因此很少有旧的 Python 代码会因此而被破坏。

  3. Python 2.2 之前的版本没有数组属性(即 shape、flat、real 和 imag)(我们使用属性功能来支持 2.2 及更高版本;因此它只与旧版本的 Python 中的 Numeric 不兼容)

还有更多次要差异,但这些是 Python 级别的主要向后兼容性问题。其中两个对于大多数使用 Python 2.2 或更高版本的用户来说应该不是问题。它确实有一些重要的增强功能,但这些不是兼容性问题。它被接受的最大问题可能是

  1. 不兼容的 C API。我们可以提供工具来简化 C 代码的适配,但我们无法使其自动化。

  2. 缺乏库。我们正在开始记录 API,提供如何添加 C 代码的示例,并添加一些标准库。在有足够的库支持(包括绘图)之前,将会有足够的功能关键质量让人们开始切换(天文学除外,这些将由我们使用 numarray 的库驱动)

  3. 小数组的性能较慢。由于其中更多的是用 Python 编写的,因此对于较小的数组来说,它的速度慢了一个数量级(但对于较大的数组(> 1MB)来说,它的速度同样快或更快)。优化已在我们的计划中,但要等到我们完成库并完成安全问题(即将完成)后才会进行。

  4. 由于 1) 和 2),目前使用它的人不多(有些人很忙,觉得 Numeric 适合他们的目的;仅仅可用性并不能让他们尝试并给出他们的意见。)

[关于整合到 Python 核心中]

好吧,这仍然是我们的目标,我们正在为此努力(我们甚至开始考虑将文档转换为 Python 标准)。有一份手册草稿可用。我估计可能需要一年时间,社区才会开始大量切换使用它(假设我们成功地让他们这样做)。

另一方面,我不认为该时间表应该必然成为它何时(或是否)被核心接受的驱动因素。它可以在此之前(它们具有不同的名称并且可以共存)或之后很久被核心接受。我认为这个决定应该在稍微不同的基础上做出。

Paul Dubois 发送电子邮件支持 Perry 的消息,宣布他很快将成为一个特定应用程序的 Numarray 用户。Paul 还提到 C API 是唯一令人讨厌的问题。他不认为小数组的性能问题是多大的问题。

基于此反馈,我预计此 PEP 将缓慢但稳定地向前发展。我希望作者最终会向我提供一个补丁集,将其代码库合并到 Python CVS 树中。这是否适用于 Python 2.3 或更高版本,我无法判断。

PEP 215 - 字符串插值 - Yee

我预见这里的争论永远不会得出明确的结论。有些人认为这是 YAGNI(你不会需要它)的明显案例,而另一些人则认为这是初学者最重要的缺失特性。我不知道哪一方是对的。即使它是一个需要的功能,语法也是有问题的:第一个 $ 在

    print $"The area of a $x by $y rectangle is $z"

非常有问题,但我看到的所有替代方案(例如,i"...")看起来都不太好。我们不能总是打开文字中的字符串插值,因为这会破坏现有代码。也许“from __future__ import interpolation”会在字符串文字中启用插值?(仅在文字中!)

还有一个问题是是否允许任意表达式,例如

    print "The area is ${x*y}"

PEP 216 - 文档字符串格式 - Zadka

这几乎没有内容。也许应该撤回?还有几个其他处理文档字符串的 PEP,特别是 256-258,我更喜欢这些。

PEP 228 - 重构 Python 的数值模型 - Zadka, van Rossum

这太过于不切实际了。有太多未解决的问题,而且许多问题甚至没有在 PEP 中提及。我认为应该拒绝;也许如果未来对此有兴趣,可以创建一个工作组或 SIG 来更深入地探索这个主题。

PEP 237 - 统一长整数和整数 - Zadka, van Rossum

这个已经被接受了,我们应该在 Python 2.3 中实现 B1 阶段。我还需要多说吗?

PEP 239 - 向 Python 添加有理类型 - Zadka

像 228 一样,我认为这不是一个现实的 PEP,它只是一堆未解决的问题。有理类型似乎会带来更多问题而不是解决问题。

也许,仅仅是也许,可以在扩展模块中用 C 实现一个高效的有理类型(当然使用 Python 长整数)。但这只是辛勤工作的问题,而且似乎没有人感兴趣。同时,如果您需要有理数,那么有大量纯 Python 实现可用(包括 Demo/classes/Rat.py)。

PEP 240 - 向 Python 添加有理文字 - Zadka

鉴于我对 239 的评论,我建议拒绝此项。

PEP 242 - 数值类型 - Dubois

除了作者之外,似乎没有人有兴趣继续研究这个。我个人认为这个想法并不是特别 Pythonic——趋势是减少数值类型,而不是增加(参见 PEP 237)。我相信作者已经表示,最好撤回 PEP。

PEP 243 - 模块存储库上传机制 - Reifschneider

当然,很好,但这应该是一个社区共同努力的项目。或许 Kapil 的模块仓库项目(Gideon,/usr/local/WWW/ftp.python.org/pub/www.python.org/sigs/catalog-sig)会给它带来新的活力?

我认为这里的问题不仅仅是软件本身,而是 (a) 建立一个能够承受整个社区访问的服务器(或一组副本),以及 (b) 动员社区将他们所有的代码提交到仓库中。

另一个问题是审查。我认为 CPAN 也没有完全解决这个问题(考虑到我听到的关于软件包无法正常工作的抱怨)。你如何知道哪些贡献是好的?计算下载量?一个“为这个软件包投票”的表格?

原始作者计划做什么?

PEP 245 - Python 接口语法 - Pelletier

Jim Fulton 说这个 PEP 太过仓促。我同意。它引入了一个新的关键字 'interface',我还不确信这是必要的。另一方面,目前在 Zope 中实现接口的方式也很丑陋,所以可能确实需要一些改进。我认为在未来某个时候,当我们有更多使用接口的经验(尤其是在 Zope 3 中)时,我们会回到这个 PEP,看看我们能用上多少。也许应该有一个特殊的“冻结”状态,意味着不拒绝,但近期也不考虑?但与“空中楼阁”不同,这个 PEP 至少有很多具体的建议,并研究了其后果。

PEP 246 - 对象适配 - Evans

直到 Alex Martelli 向我解释之后,我才理解这个 PEP 是关于什么的。我认为它类似于 Zope 3 中的一个操作,它查找给定对象的适配器,该适配器实现了给定的接口。如果对象本身实现了该接口,则返回对象本身;否则,会系统地搜索已注册的适配器表,以找到最合适的适配器。

但这就是我对此主题的全部了解,我认为在找到一种描述接口的标准方式之前,它应该保持为一个好主意。所以我认为它将具有“冻结”状态(见上文),至少与 PEP 245 一样长的时间。

我不得不承认,我从未完整阅读过整个 PEP,当然也没有尝试阅读和理解规范或示例实现,所以也许我仍然理解有偏差。

PEP 254 - 使类更像类型 - van Rossum

这个 PEP 旨在描述对经典类实现的更改,使其更接近新式类。我还没有开始这项工作,而且我认为也许没有必要——经典类实现可以保持原样,直到它在 Python 3000 中被简单地删除。在某个时候,当我们相信大多数用户都在使用新式类时,我们应该为使用旧式类添加警告。这个 PEP 可以用来描述这些警告的时间框架。但在此之前,我们应该首先确保整个标准库(以及演示和工具)都使用新式类。这甚至不会在 Python 2.3 中发生。此外,这可能会破坏用户代码,这些代码继承了特定的标准类,例如,如果用户定义了一个依赖于强制转换的子类,而新式类不支持强制转换。

PEP 256 - 文档字符串处理系统框架 - Goodger

PEP 257 - 文档字符串约定 - Goodger, van Rossum

PEP 258 - DPS 通用实现细节 - Goodger

我将一起讨论这些。我相信 David Goodger 正在做很好的工作,我仍然在 doc-sig 中看到他频繁的帖子。但我根本没有关注这项工作。由于这不影响语言,只是一个约定,我并不特别关心这个。

PEP 262 - 已安装 Python 包的数据库 - Kuchling

我认为这是一个 distutils 的“空中楼阁”项目?也许有人应该实现它;我对此没有意见,但我自己并没有特别感到需要。

PEP 263 - 定义 Python 源代码编码 - Lemburg

这个非常接近被提交了。Martin 和 Marc-Andre 正在讨论实现方案。当他们准备好时,我想我会直接批准它。一位外部专家 Stephen Turnbull 提出了严重反对意见,他希望我们用 UTF-8 定义纯语言,并将编码实现为特定于站点的(?)钩子。但没有人同意他的观点,我亲自回应说,我认为最好按照 MAL 的方式去做。

PEP 265 - 按值排序字典 - Griffin

这是一个对提议者来说非常重要的小想法,但在我看来,它试图解决一个可以通过其他方式更好地解决的问题,例如,通过教新手正确的算法/习惯用法。我注意到该 PEP 使用了马虎的语言,例如,它谈论“排序字典”,而字典本身永远不会被排序——该 PEP 仅提出返回按排序顺序排列的项目或键的方法。

该 PEP 也缺乏明确性:它提出了一系列替代方案,我猜我应该从中选择我最喜欢的一个。这又让我成了坏人。:-)

最后,提议的“reversed=<bool>”可选参数似乎完全是特定于应用程序的。

我想拒绝这个,因为它没有以足够通用的方式解决足够通用的问题,它只是让字典 API 变得混乱。我宁愿添加 dict.popitem(key)。

PEP 266 - 优化全局变量/属性访问 - Montanaro

PEP 267 - 优化对模块命名空间的访问 - Hylton

PEP 280 - 优化对全局变量的访问 - van Rossum

这三个应该一起考虑;最多可以实现其中一个(或者可能是混合的)。我希望最终实现其中一个,因为我认为它可能会带来很大的性能提升:不仅避免了全局变量和内置函数的字典查找,而且还可以在解析器中识别某些内置函数,并生成知道内置函数作用的代码,例如 len(x) 的操作码和“for i in range(x, y, z)”的特殊代码。

我认为 Montanaro 的提议过于复杂。我喜欢 Hylton 的版本和我自己的版本一样;他的版本有一些可选功能(例如,支持表示“模块.属性”的全局属性),我认为不值得增加额外的复杂性。

在上次 PythonLabs 会议上,我们决定首先做一些不那么雄心勃勃的事情,看看在 2.3 之前是否有时间在完成这些之后做更多的事情。不那么雄心勃勃的事情是重构编译器,使用更合适的抽象语法树,并引入显式的多遍处理。我预测仅此一项在 2.3 beta1(7 月 17 日)之前剩余的时间里就已经很难做到了。

PEP 268 - 扩展 HTTP 功能和 WebDAV - Stein

我完全支持这个,但这是库开发工作,我不会去做。

似乎作者已经放弃了,而且没有人接手。在 sandbox/Lib 目录(奇怪的名称)中有一个 2001 年 9 月的实际原型;也许我们应该催促作者完成这项工作,或者问问他在等什么。

PEP 269 - Python 的 Pgen 模块 - Riehl

我知道 Martin von Loewis 不喜欢这个(因为它缺乏通用性,例如,除了定义保留字集之外,没有办法更改词法分析器),但我认为它对于那些尝试使用类似 Python 的语言(例如,添加新关键字和语法的 Python 预处理器)的人来说可能有些用处。由于 pgen 与 Python 发行版紧密绑定,因此将使 pgen 可供 Python 程序员使用的扩展也应该包含在 Python 发行版中是有意义的。

因此,我们应该问问作者是否计划实现它。如果没有,那么它可能会因缺乏兴趣而被放弃。

PEP 270 - 列表对象的 uniq 方法 - Petrone

与 PEP 265 的故事相同。正如关于这个主题的激烈的食谱条目所证明的那样,要完全通用地做到这一点要比看起来困难得多。该 PEP 是未完成的:它甚至没有指定所需的语义!而且为什么没有包含作者的实现,如果它只有 20 行?

我建议拒绝这个,以节省作者的工作(他仍然应该公开他的实现)。

PEP 273 - 从 Zip 存档导入模块 - Ahlstrom

我喜欢这个概念。我没有详细研究该 PEP 或提议的实现,所以我不知道它是否总是做正确的事情。我希望它能进入 2.3。

PEP 274 - 字典推导式 - Warsaw

如果我们采用字典推导式,那么这个 PEP 说明了所有需要说明的内容。但我甚至不想在 Python 2.3 中考虑这个问题;我认为它是一个太小的特性。

如果有补丁形式的工作实现,这将更容易采用。

有时,如果可以使用卫生宏或其他类型的预处理器或其他东西来定义类似这样的东西,并从模块中导入,而不是需要在解析器、字节码编译器和虚拟机中进行大量破解,那就太好了。

PEP 275 - 根据多个值切换 - Lemburg

我仍然不相信我们需要一个 switch 语句,并且提议的语法存在问题:例如,为什么只允许常量?为什么不允许范围?此外,它提出了许多不同的替代方案,而没有选择一个。

然而,该 PEP 提出的第一个替代方案并没有添加任何新语法,而只是建议解析器识别某种常见的模式并为其生成更好的代码。我完全支持这一点,前提是能够证明生成的代码要么速度明显更快,要么体积明显更小,或者两者兼而有之。在上面关于 PEP 266、267、280 的评论中提出的编译器重构之后,这个项目可能会容易得多。

PEP 276 - int 的简单迭代器 - Althoff

我犯了一个错误,告诉作者我觉得这很丑陋。不管用什么词,我确实认为这与 Pythonic 相悖。对我来说

    for i in 12:
        print i

看起来就不对劲。也许

    for i in len(L):
        print i, L[i]

很有吸引力,但不知何故,我只是认为这不是正确的解决方案。

PEP 277 - Windows NT 的 Unicode 文件名支持 - Hodgson

我不知道这个的状态,但我相信这已经实现或者至少接近实现了?这在德国人中存在争议吗?

PEP 278 - 通用换行符支持 - Jansen

我给 Jack 发了一堆唱反调的问题。这个问题是真实存在的,我希望看到它得到解决,但我担心这有点太像黑客行为了。这是列表

  • source() 调用到底是什么?
  • 为什么不支持为输出文件设置分隔符?
  • 't' 模式与在 Windows 上使用此模式来显式调用默认文本转换模式相冲突。
  • 为什么不能将 't' 与 '+' 一起使用?据我所知,Windows 上的文本模式支持 '+'。
  • 这如何与 xreadlines 交互?与 "for line in file" 交互?
  • 为什么选择默认关闭的编译时选项?那是在自找麻烦;打开它的人会编写使用 't' 模式的代码,然后发现它是不可移植的。
  • 你说 import 使用 't' 模式。从字符串解析源代码怎么办?Unicode 字符串怎么办?
  • 我想我需要对你关于锁的评论有更多的澄清。如果可以滥用实现来创建核心转储,我不会支持它。

PEP 279 - 增强的生成器 - Hettinger

2002 年 3 月 28 日: 作者采纳了我的建议,删除了可重启迭代器的想法,我在之前的评论中称之为邪恶的。这是我目前的评论

  1. 新的内置函数:indexed()

    我喜欢以某种方式并行迭代序列及其索引集的想法。将其作为内置函数很好。

    我不喜欢“indexed”这个名字;形容词不适合作为函数名。也许 iterindexed() 更好?

    我不喜欢 start 和 stop 参数。如果我看到类似这样的代码:

         for i, j in iterindexed("abcdefghij", 5, 10): print i, j
    
    我会期望它打印:
         5 f
         6 g
         7 h
         8 i
         9 j
    
    而 PEP 中的规范会打印:
         5 a
         6 b
         7 c
         8 d
         9 e
    

    非常令人困惑。我建议移除 start/stop 参数,或者更改规范为:

         def iterindexed(sequence, start=0, stop=None):
             i = start
             while stop is None or i < stop:
                 try:
                     item = sequence[i]
                 except IndexError:
                     break
                 yield (i, item)
                 i += 1
    

    这将有效性限制为仅限序列(而不是所有可迭代集合),但优点是使 iterindexed(x, i, j) 迭代 x[i:j] 时,报告的索引序列是 range(i, j) -- 否则就不那么容易实现了。

    简化版本仍然很有吸引力,因为它允许传入任意迭代器:

         def iterindexed(collection):
           i = 0
           it = iter(collection)
           while 1:
             yield (i, it.next())
             i += 1
    
  2. 生成器推导式

    我认为这不值得麻烦。我预计将其破解到代码生成器中会花费大量精力:它必须创建一个单独的代码对象才能成为生成器。列表推导式是内联的,所以我预计生成器推导式代码生成器无法与列表推导式代码生成器共享太多。而且这对于不常见且容易通过编写一个 2 行辅助函数来完成的事情来说。换句话说,投资回报率不够高。

  3. 生成器异常传递

    这是 PEP 似乎最薄弱的地方。没有真正的动机(“这是一个真正的缺陷”不算数 :-)。没有关于应该如何实现的提示。示例中生成器主体中有一个“return log”语句,这在当前是非法的,我无法弄清楚这个值会返回到哪里。这个例子看起来不需要生成器,如果需要,可以通过设置一个全局“请停止”标志并再次调用 next() 来轻松停止生成器。(如果你不喜欢全局变量,可以将生成器设为一个类的方法,并将停止标志设为一个实例变量。)

PEP 281 - 使用 range 和 xrange 的循环计数器迭代 Hetland

这是 PEP 212 中 irange() 的一个替代方案(该方案被拒绝了,但没有文本解释为什么被拒绝)。只要我们要引入一个返回 range(0,len(sequence)) 的(惰性或其他)版本的 FOO(sequence) 符号,我认为使用 FOO==range 比其他任何东西都更令人困惑。换句话说,如果我们必须这样做,请为其发明一个新名称。

PEP 282 - 日志系统 - Mick

我要求了这个,甚至还没有看过。但我已经喜欢它了!我希望这可以在 2.3 中实现。

PEP 284 - 整数 for 循环 - Eppstein, Ewing

这是解决一些人觉得:

    for i in range(10):

太丑陋的又一种方法。我对这个的主要抱怨是:

    for 0 <= i < 10:

将索引变量放在中间,而不是紧跟在 for 关键字之后。而且在下限是变量的情况下,这对随便看看的读者来说是令人困惑的:

    for i <= j < k:

看起来类似于:

    for i in j, k:

但在一种情况下,循环计数器是 j,在另一种情况下,循环计数器是 i。

这个 PEP 的好处在于,它引用并评论了所有以前试图解决这个问题的 PEP(204、212、276 和 281)。

我认为当前的解析器生成器必须被严重滥用才能允许以下两个语法选项:

    for <target_list> in <expression_list>

    for <expression> <comparison> <target> <comparison> <expression>

因为 <target_list> 可以以 <expression> <comparison> 开头。

结束语

哇!就这样了。嗯,在被放弃的类别中还有一些 PEP 可能值得评论,但我会等到有人想重新启动它们。我们绝对应该更清楚地区分被拒绝的和被推迟的 PEP。而且不应该有任何被拒绝的 PEP 没有被拒绝的解释。