12

我对热身“Python 2 还是 Python 3?”不感兴趣。问题(即使我发现的最近一个问题已经超过一年了),但我偶然发现了这个说法

如果您的文件以以下行开头,您可以在 Python 2 下编写 Python 3 代码:

from __future__ import absolute_import, division, generators, unicode_literals, print_function, nested_scopes, with_statement

有了该行,您的代码将适用于 Python 2 或 Python 3。可能在极少数情况下它不起作用,但我没有发现任何情况,

这是真的?这一行是否足以确保您编写的代码将在 Python 2.x(我假设 >=2.5)和 3.x(假设导入的模块在两者中都可用)上运行?

4

6 回答 6

8

我会说不,这是胡说八道。即使有了这些导入,Python 2 和 3 之间仍然存在显着差异:例如,input()在 Python 3 中就像raw_input()在 Python 2 中一样;range()在 Python 3 中就像xrange()在 Python 2 中一样。在这种情况下,只要范围很小,xrange()您就可以range()在 Python 2 中使用,但如果它们很大,那么您的程序在 Python 2 和蟒蛇 3。

您可以在代码中添加类似这样的内容:

try:
    range = xrange
    input = raw_input
except NameError:
    pass

但是你必须找到所有这些边缘情况并修复它们。例如,在 Python 3 中有返回迭代器的keys()andvalues()方法,dict但在 Python 2 中有列表,因此您需要编写一个dict“修复”它的子类(然后永远不要在代码中使用字典文字而不包装它们,因为否则将是内置dict类型)。

我想,通过使用__future__和各种修复,并限制自己在这样创建的 Python 子集中编写代码,该子集将在 2.x 和 3.x 下运行,有可能编写在两者中运行的代码版本。不过,看起来工作量很大。有一个2to3实用程序是有原因的...

于 2012-06-19T14:46:13.120 回答
7

“这取决于”

否:将这些导入添加到您的 Python 2 代码不会使其在 Python 3 下运行。

是的:有了这些导入,您可以编写在 Python 2 和 Python 3 下运行的代码。

但是:再一次,你也可以在没有这些导入的情况下做到这一点,其中有几个,例如unicode_literals已经证明根本没有帮助。generators并且with_statement与 Python 2 到 Python 3 完全无关,这些是 Python 2 版本中添加的功能。

所以总而言之,这些进口有点像红鲱鱼,而且这种说法错多于正确。

然而,这并不意味着编写同时在 Python 2 和 Python 3 下运行的代码是不可能的,甚至是非常困难的。有关更多信息,请参见http://python3porting.com/

于 2012-06-21T02:54:49.473 回答
5

这并非不可能,具体取决于您的代码库的需求。您可能会发现(2 * 3,哈哈)库必不可少;另一个有用的工具是python-modernize,它尝试将您的代码转换为交叉兼容状态。

于 2012-06-19T15:19:38.880 回答
4

它会增加它的可能性,但是有些东西不能从__future__导入中获得,有些东西在 3.x 中会被删除。

在我的脑海中,您仍然可以使用在 3.x 中删除的参数元组解包,并且您将无法使用在 3.x 中引入的带有星号运算符的漂亮元组解包。

例如:

def some_function((x, y), magnitude): #This has been removed in 3.x
    pass

x, *y = (1, 2, 3) #This does not exist in 2.x

就是说,要小心避免此类事情,您绝对可以编写适用于两个版本的代码,是的。

显然,这也仅适用于将功能向后移植到其中的 2.x 版本。正因为如此,该行中的某些行实际上是完全没有意义的——例如,没有理由导入generators,因为任何可以导入 with 语句的版本都已经有生成器作为标准工作。也一样nested_scopes

一般来说,我建议只为 3.x 编写 - 安装和使用这两个版本没有障碍。如果你真的非常需要 2.x 支持,那么就为 2.x 编写尽可能多的向后移植的特性,并使用 2to3 来清理其他任何东西。

于 2012-06-19T14:30:49.800 回答
3

不。其他人指出了一些差异,还有其他人。最基本的一点是 Python 3 原生字符串是多字节的——这在与单字节机制(例如与其他进程的管道)通信时会引发问题。其他包括模块重命名(Tkinter 到 tkinter),True 和 False 现在是关键字。

甚至对比也可能不一样,以下不正确的代码:

num = 42
txt = "3"

if txt < num:
    print ('Wow!')
else:
    print ('Doh!')

在 Py3 上产生 a TypeError,但在 Py2 上不产生。

已经提到了拆包。字典方法items()keys()values()返回视图对象(在 2.7 上使用不同的方法名称)。在 Py3 中,迭代器被更多地使用,例如从map()and中返回filter(),等等......

于 2012-06-19T15:22:52.387 回答
1

你可以使用future包:pip install future

In [1]: range(10)
Out[1]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: from future.builtins import range

In [3]: range(10)
Out[3]: range(0, 10)

这是他们的备忘单和更多示例: http: //python-future.org/compatible_idioms.html

于 2014-08-14T07:59:28.903 回答