支持类型统一 python 2/3 版本

Supporting types in unified python 2/3 version

我有一些代码是用 python 2.7.x 编写的,我正试图使其与 python 3.x 兼容。我已经解决了将代码转换为在两个版本下工作的大部分问题,但需要处理 int/long 类型的建议。

许多统一 int 和 long 类型的工作发生在更早的 (2.4.x) 版本中,并且在 V3 中完全删除了区别('1L' 格式不再有效)。同时,修改了类型模块以删除对已内置类型的引用,并删除了多余的 'long' 内置类型。

所以在V2.x下我仍然需要支持这样的代码:

if type(var) == int or type(var) == long :
     do_stuff

if type(var) == int :
     do_int_stuff
elif type(var) == long :
     do_long_stuff

但是对于 V3 来说,长期没有内置 class,也不需要 do_long_stuff,这与正常的 do_int_stuff 不同。内置 class 类型变量 'long' 不再定义,因此此代码将失败并出现 NameError。

一个简单的解决方案是将 'long' 定义为 None 或 v3 下的其他一些无意义的类型,理解 type(var) != long 对于任何 var。 v2.x 下定义的 long 内置 class 类型将保持不变。

if sys.version_info.major == 3 :
     long = None

None 是最好的使用价值吗?在我的例子中,设置 'long = int' 不是我想要使用的。

首先,你不应该使用type(obj) == type_obj;始终使用 isinstance() function。你很少需要忽略子类,如果你确实需要忽略子类,你可以使用 type(obj) is type_obj 代替。

isinstance() 可以采用 元组 类型:

isinstance(obj, (int, long))

然后允许您使用变量:

try:
    integer_types = (int, long)
except NameError:
    integer_types = int

if isinstance(obj, integer_types):

请注意,我在这里根据 NameError 换出了 integer_types 定义,而不是在版本测试中。现在您的代码兼容 Python 2 和 3,以及任何其他没有 long 类型的假设 Python 构建。

我喜欢 Martijn 的回答,但我会把它包装成

import sys

if sys.hexversion < 0x3000000:
    # Python 2.x
    is_int  = lambda x: isinstance(x, (int, long))
    is_long = lambda x: isinstance(x, long)
else:
    # Python 3.x
    is_int  = lambda x: isinstance(x, int)
    is_long = lambda x: False

你可以像这样使用

if is_int(var):
    do_something(var)

if is_long(var):
    do_long_stuff(var)
elif is_int(var):
    do_int_stuff(var)

一般来说,如果我要在 python 中进行类型检查,我更愿意尽可能检查抽象基础 class。在这种情况下,存在 numbers.Integral 可能会很好地工作...

>>> import numbers
>>> isinstance(1, numbers.Integral)
True
>>> isinstance(1L, numbers.Integral)
True
>>> isinstance(1., numbers.Integral)
False

这应该适用于 python2.x 和 python3.x。


当然,如果数字是 int ,这个答案(以及迄今为止提出的所有其他答案)假设您实际上想要做同样的事情一个long。 任何想要根据它是否具有 intlong 来做不同事情的代码看起来很可怕,并且尝试将其直接移植到 python3.x 作为 long 是没有希望的不存在使得该代码路径实际上已失效。