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 的话:
[...] 新版本越来越向后兼容。事实上,主要区别在于:
- 当标量与数组组合时的强制转换规则差异。在科学 Python BoF 会议上,大家一致认为这个改变是件好事。
- 类型由类型对象而不是单字符代码表示。我们已将其实现为向后兼容,因此应该很少有旧的 Python 代码会因此而损坏。
- 对于 2.2 之前的 Python 版本,没有数组属性(即 shape、flat、real 和 imag)(我们使用属性功能来支持 2.2 及更高版本;因此它仅与旧版 Python 的 Numeric 不兼容)
还有一些较小的差异,但这些是 Python 层面主要的向后兼容性问题。其中两个对于大多数使用 Python 2.2 或更高版本的用户来说应该不是问题。它确实有许多重要的增强功能,但这些不是兼容性问题。可能它被接受的最大问题是
- 不兼容的 C API。我们可以提供工具使其更容易适应 C 代码,但我们无法使其自动化。
- 缺乏库。我们现在开始记录 API,提供如何添加 C 代码的示例,并添加一些标准库。在功能达到临界质量(足以让人们开始切换,除了天文学领域,这将由我们使用 numarray 的库驱动)之前,必须有足够的库支持(包括绘图)。
- 小数组性能较慢。由于它更多地用 Python 编写,因此对于小数组(但对于大数组(> 1MB)则同样快或更快)来说,速度会慢一个数量级。优化在我们的计划中,但在我们完成库和安全问题(即将完成)之前不会进行。
- 由于 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 - Docstring 格式 - Zadka
内容很少。也许应该撤回?还有几个其他 PEP 处理 doc string,尤其是 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 的版本和我的版本一样好;他的版本有一些可选功能(例如支持表示“module.attribute”的全局变量属性),我认为这些功能不值得增加的复杂性。
在上次 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 提出的第一个替代方案没有添加任何新语法,只是提议解析器识别某个常见模式并为其生成更好的代码。我完全赞成这一点,前提是能够证明生成的代码要么显著更快,要么显著更小,或两者兼而有之。在对 PEPs 266、267、280 的评论中提议的编译器重构之后,这个项目可能会容易得多。
PEP 276 - 整数的简单迭代器 - 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 发了一堆“魔鬼代言人”的问题。这个问题是真实存在的,我希望看到它得到解决,但我担心这太像一个 hack 了。以下是问题列表:
- source() 调用到底是什么?
- 为什么不支持为输出文件设置分隔符?
- 't' 模式与 Windows 上使用此模式显式调用默认文本转换模式相冲突。
- 为什么 't' 不能与 '+' 一起使用?据我所知,Windows 上的文本模式支持 '+'。
- 这与 xreadlines 如何交互?与 "for line in file" 如何交互?
- 为什么满足于一个默认关闭的编译时选项?这会带来问题;打开它的人会编写使用 't' 模式的代码,然后发现它不可移植。
- 你说 't' 模式被 import 使用。从字符串解析源代码呢?Unicode 字符串呢?
- 我认为我需要你澄清关于锁的评论。如果实现可以被滥用以创建核心转储,我不会支持它。
PEP 279 - 增强型生成器 - Hettinger
2002 年 3 月 28 日:作者采纳了我的建议,删除了可重启迭代器这个想法,我曾在之前的评论中称之为邪恶。以下是我目前的评论:
- 新的内置函数: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
- 生成器推导式
我认为不值得为此费力。我预计将其植入代码生成器需要大量工作:它必须创建一个单独的代码对象才能成为生成器。列表推导式是内联的,所以我预计生成器推导式代码生成器无法与列表推导式代码生成器共享太多。而这对于不那么常见且通过编写一个两行辅助函数即可轻松完成的事情来说,投资回报率不够高。
- 生成器异常传递
这是 PEP 看起来最薄弱的地方。没有真正的动机(“这是一个真正的缺陷”不算数 :-)。也没有暗示应该如何实现。示例中生成器主体有一个“return log”语句,这在目前是非法的,我无法弄清楚这个值会返回到哪里。这个示例看起来不需要生成器,如果需要,通过设置一个全局“请停止”标志并再调用一次 next() 很容易停止生成器。(如果你不喜欢全局变量,可以将生成器设为类的某个方法,并将停止标志设为实例变量。)
PEP 281 - 使用 range 和 xrange 进行循环计数迭代 - Hetland
这是 PEP 212 中 irange() 的替代方案(该 PEP 已被拒绝,但没有解释拒绝原因的文本)。只要我们引入 FOO(sequence) 这种表示法,它返回 range(0,len(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。而且任何被拒绝的 PEP 都不应该没有拒绝的解释。