Python 2.1[.x] 和 2.2[.x] 之间的不兼容性
Python 2.2.2 和 Python 2.2.3 之间的不兼容性
Python 2.2.2 和 Python 2.2.3 之间以下可见的差异是故意的。
- 不再可能使用 object.__setattr__ 来规避
- 对设置类型对象属性的限制。
- list.extend() 适用于任何可迭代对象。
- 在 pdb 中,你不能再使用负数启用断点。
- 数字。
- Bastion.py 和 rexec.py 模块已禁用。
- 对 __class__ 赋值有一些额外的限制。
- WeakKeyDictionary 的 __delitem__ 已改进并修复,
- 但可能会改变可见行为。
有关更多详细信息,请参阅NEWS 文件。
Python 2.1[.x] 和 Python 2.2[.x] 之间的不兼容性
Python 2.2 和以前版本之间以下可见的差异是故意的。
- 此处未列出各种可能发出警告的已弃用模块和功能:警告不应影响程序的正确执行,并且可以使用命令行选项或以编程方式禁用;请参阅 warnings 模块的文档。
- 此处也未列出以前是错误的新结构(例如,“key in dict”现在是一个有效的测试,而以前它总是会引发异常)。
- dir() 函数的行为与 Python 2.1 及更早版本不同。通常,dir() 返回的信息比 2.1 中更多。例如,dir([]) 还报告重载各种运算符的特殊方法(“__add__”、“__getitem__”、“__len__”等)以及“__class__”。对于类(经典类和新式类),它返回类的属性以及基类的属性。
- 不再支持特殊属性 __members__ 和 __methods__(对于大多数内置类型)。请改用新的改进的 dir() 函数。
- type("").__name__ == "str" # 以前是 "string"
- type(0L).__name__ == "long" # 以前是 "long int"
- 溢出 int 操作返回相应的 long 值,而不是引发 OverflowError 异常。
- 如果 long 太大而无法表示为 C double,则 long 到 float 的转换现在会引发 OverflowError。这在大多数平台上以前会返回一个“无穷大”值。
- 三参数内置 pow() 不再允许第三个非 None 参数,如果前两个参数中的任何一个是浮点数,或者如果两者都是整数类型且第二个参数是负数(在后一种情况下,参数会转换为浮点数,因此这实际上是相同的限制)。
- 一个旧的词法分析器 bug 允许带有不完整指数的浮点文字,例如 1e 和 3.1e-。此类文字现在会引发 SyntaxError。
- 在 2.2 中,嵌套作用域是标准的(在 2.1[.1] 中,它们通过“from __future__ import nested_scopes”按模块启用)。这可能会改变以下代码的含义
- def f(str)
- def g(x): return str(x) return g
在此示例中,内部函数 g() 中对 str 的使用现在指向外部函数 f() 中的参数 str;以前(没有嵌套作用域),它将指向内置函数 str。
- 未绑定方法对象的 im_class 字段设置方式不同。在以前的版本中,im_class 字段设置为定义该方法的类。现在它设置为用于创建方法对象的类。例如
- class A
- def meth(self): ...
- class B(A)
- ... # 未定义 meth
- class C(A)
- def meth(self)
- B.meth(self) # 错误,C 不继承自 B
这段代码以前意外地有效,即使 B 不是 C 的基类,因为 B.meth.im_class 被设置为 A,而 A 是 C 的基类!大概很久以前继承树不同,C 确实继承自 B;当它被更改时,向上调用没有被修复。当不相关的类 B 获得 meth() 的新定义时,C 将会中断。此外,以前,B().meth.im_class 将返回 A;现在它返回 B(因为它是一个绑定到 B 实例的方法)。
- GC 模块的 C API 已发生不兼容更改。为支持 2.1 版 GC 模块而编写的扩展仍将编译,但 GC 功能将禁用。
- gc.garbage 的内容不同;它以前包含所有不可收集的循环;现在它只包含在具有 __del__ 方法的不可收集循环中的对象。
- 字典项的哈希顺序与以前的版本不同。(没有代码应该依赖此顺序,但很容易忘记这一点。)
- 在编译时对 __debug__ 赋值会引发 SyntaxError。
- UTF-16 编解码器已修改以更符合 RFC。它现在只会在字符串开头删除 BOM 字符,并且只有在以本机模式运行(UTF-16-LE 和 -BE 不会删除开头的 BMO 字符)时才删除。
- 许多错误消息都不同;在某些情况下,错误条件会引发不同的异常(最常见的情况是 TypeError 和 AttributeError 互换)。
经典类和新式类之间的差异
以下经典类和新式类之间的差异在将经典类转换为新式类时可能需要注意。由于 Python 的以前版本不支持新式类,因此这些不能被认为是真正的 bug,但由于我们已尽力使新式类的行为向后兼容,因此注意这些差异很重要。(当然还有更多差异在您从头开始编写新式类时会变得相关;此列表仅列出与经典类转换相关的行为更改。)
- 方法解析顺序不同;请参阅教程。
- 重载二进制运算符(__add__ 等)的新式类不能依赖 __coerce__ 方法来强制转换参数;另一个参数将是最初存在的任何内容。因此,如果 x 是一个定义了 __add__ 方法的新式类实例,x+1 会导致调用 x.__add__(1)。方法实现必须分析另一个参数的类型,以便能够正确实现操作。如果方法实现决定它不知道如何为这种特定参数类型组合实现操作,它应该返回特殊单例值 NotImplemented。(此行为与缺少 __coerce__ 方法的经典类相同;不同之处在于 __coerce__ 方法被新式二进制运算符忽略。)
- 新式类实例仅当新旧类的 C 级结构布局相同时才允许对其 __class__ 属性赋值。这可以防止将列表更改其 __class__ 使其成为字典等灾难。
- 新式类对象不支持对其 __bases__ 属性赋值。
- 新式类对象不支持对其 __name__ 属性赋值。
- (我确信还有更多与经典类转换为新式类相关的差异,但我现在想不起来。)
要报告未在上面列出的 bug,请始终使用 SourceForge Bug Tracker。如果您有补丁,请使用 SourceForge Patch Manager。请提及您正在报告 2.2.3 中的 bug!
