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

Python 2.1[.x] 和 2.2[.x] 之间的兼容性问题

<h3>Python 2.2.2 和 Python 2.2.3 之间的兼容性问题</h3>

<p>Python 2.2.2 和 Python 2.2.3 之间的以下可见差异是故意的。

<ul>

<p><li>现在无法使用 object.__setattr__ 来绕过
对设置类型对象属性的限制。

<p><li>list.extend() 可与任何可迭代对象一起使用。

<p><li>在 pdb 中,您不能再使用负数启用断点
数字。

<p><li>Bastion.py 和 rexec.py 模块已禁用。

<p><li>对 __class__ 赋值有一些额外的限制。

<p><li>WeakKeyDictionary 的 __delitem__ 已得到改进和修复,
但可能会改变可见行为。

</ul>

有关更多详细信息,请参阅 <a href="../NEWS.txt">NEWS 文件</a>。

<h3>Python 2.1[.x] 和 Python 2.2[.x] 之间的兼容性问题</h3>

<p>Python 2.2 与以前版本之间的以下可见差异是故意的。

<ul>

<p><li>这里没有列出各种已弃用的模块和功能,这些模块和功能可能会发出警告:这些警告不应影响程序的正确执行,并且可以使用命令行选项或以编程方式禁用它们;请参阅 warnings 模块的文档。

<p><li>这里也没有列出以前是错误的新结构(例如,“key in dict”现在是有效的测试,而以前它总是会引发异常)。

<p><li>dir() 函数的行为与 Python 2.1 及更早版本不同。通常,dir() 返回的信息比它在 2.1 中返回的信息更多。例如,dir([]) 还报告了重载各种运算符的特殊方法('__add__'、'__getitem__'、'__len__' 等)以及 '__class__'。对于类(经典类和新式类),它返回类本身以及基类的属性。

<p><li>特殊属性 __members__ 和 __methods__ 不再受支持(对于大多数内置类型)。请改用新的改进的 dir() 函数。

<p><li>type("").__name__ == "str" # 以前是 "string"

<p><li>type(0L).__name__ == "long" # 以前是 "long int"

<p><li>整数运算溢出将返回相应的长整数值,而不是引发 OverflowError 异常。

<p><li>如果长整数太大而无法表示为 C 双精度浮点数,则将长整数转换为浮点数现在会引发 OverflowError。这以前在大多数平台上会返回“无穷大”值。

<p><li> 内置函数 pow() 的三参数版本不再允许第三个参数为非 None,如果前两个参数中有一个是浮点数,或者两个参数都是整数类型且第二个参数为负数(在这种情况下,参数会被转换为浮点数,因此实际上是相同的限制)。

<p><li>一个旧的词法分析器错误允许浮点数字面量带有不完整的指数,例如 1e 和 3.1e-。现在,这样的字面量会引发 SyntaxError。

<p><li>嵌套作用域在 2.2 中是标准的(在 2.1[.1] 中,它们是通过 "from __future__ import nested_scopes" 在每个模块中启用的)。这可能会改变以下代码的含义

<pre>
def f(<font color="red">str</font>)
def g(x): return <font color="red">str</font>(x) return g

System Message: WARNING/2 (<string>, line 84)

Definition list ends without a blank line; unexpected unindent.

</pre>

在这个例子中,内部函数 g() 中使用 <font color="red">str</font> 现在指的是外部函数 f() 中的参数 <font color="red">str</font>;之前(没有嵌套作用域),它指的是内置函数 <font color="blue">str</font>。

<p><li>未绑定的方法对象它们的 im_class 字段设置不同。在之前的版本中,im_class 字段被设置为 <i>定义</i> 该方法的类。现在它被设置为用来创建方法对象的类。例如

<pre>
class A
def meth(self): ...
class B(A)
... # 不定义 meth
class C(A)
def meth(self)
B.meth(self) # 错误,C 不继承自 B

System Message: WARNING/2 (<string>, line 105)

Definition list ends without a blank line; unexpected unindent.

</pre>

这段代码之前意外地工作了,即使 B 不是 C 的基类,因为 B.meth.im_class 被设置为 A,而 A 是 C 的基类!可能很久以前继承树是不同的,C 确实继承自 B;当它被改变时,上调用没有被修复。当不相关的类 B 获得 meth() 的新定义时,C 会崩溃。此外,之前,B().meth.im_class 会返回 A;现在它返回 B(因为它是一个绑定到 B 实例的方法)。

<p><li>GC 模块的 C API 发生了不兼容的改变。为支持 GC 模块的 2.1 版本编写的扩展仍然可以编译,但 GC 功能将被禁用。

<p><li>gc.garbage 的内容不同;它以前包含所有不可回收的循环;现在它只包含具有 __del__ 方法的不可回收循环中的对象。

<p><li>字典项的哈希顺序与之前的版本不同。(没有代码应该依赖于这个顺序,但很容易忘记这一点。)

<p><li>对 __debug__ 的赋值在编译时引发 SyntaxError。

<p><li>UTF-16 编解码器被修改为更符合 RFC。它现在只会在字符串开头移除 BOM 字符,并且只有在以原生模式运行时(UTF-16-LE 和 -BE 不会移除开头的 BMO 字符)。

<p><li>许多错误消息不同;在某些情况下,错误条件会引发不同的异常(最常见的是 TypeError 和 AttributeError 被互换的情况)。

</ul>

<h3>经典类和新式类之间的差异</h3>

<p>将经典类转换为新式类时,以下经典类和新式类之间的差异可能需要关注。由于之前的 Python 版本不支持新式类,这些不能被认为是真正的错误,但由于我们已经尽力使新式类的行为向后兼容,因此需要注意这些差异。(当然,如果你从头开始编写新式类,还有更多差异会变得相关;此列表只列出了与经典类转换相关的行为变化。)

<ul>

<p><li>方法解析顺序不同;请参阅 <a href="../descrintro/#mro">教程</a>。

<p><li>重载二元运算符(__add__ 等)的新式类不能依赖于 __coerce__ 方法来强制转换参数;另一个参数将是最初存在的任何参数。因此,如果 x 是一个定义了 __add__ 方法的新式类实例,x+1 会导致调用 x.__add__(1)。方法实现将不得不分析另一个参数的类型,以便能够正确地实现操作。如果方法实现决定它不知道如何为这种特定的参数类型组合实现操作,它应该返回特殊的单例值 NotImplemented。(这种行为与缺少 __coerce__ 方法的经典类相同;区别在于 __coerce__ 方法被新式二元运算符忽略。)

<p><li>新式类实例只允许对它们的 __class__ 属性进行赋值,前提是旧类和新类的 C 级结构布局相同。这可以防止灾难,例如获取一个列表并更改其 __class__ 使其成为一个字典。

<p><li>新式类对象不支持对它们的 __bases__ 属性进行赋值。

<p><li>新式类对象不支持对它们的 __name__ 属性进行赋值。

<p><li>(我确信还有更多与将经典类转换为新式类相关的差异),但我现在想不起来。)

</ul>

<p>要报告上面未列出的错误,请始终使用 SourceForge <a href="http://sourceforge.net/bugs/?group_id=5470">Bug Tracker</a>。如果你有补丁,请使用 SourceForge <a href="http://sourceforge.net/patch/?group_id=5470">Patch Manager</a>。请说明你正在报告 2.2.3 中的错误!