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

时间:2015-02-10 16:33:14

标签: python python-2.7 python-3.x

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

统一int和long类型的大部分工作都发生在早期版本(2.4.x)中,并且在V3中完全消除了区别('1L'格式不再有效)。同时修改了types模块以删除对已经内置的类型的引用,并删除了冗余的“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,没有内置类很长,并且不需要do_long_stuff与普通的do_int_stuff不同。不再定义内置类类型变量'long',因此此代码将因NameError而失败。

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

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

没有最佳价值吗?在我的情况下,设置'long = int'不是我想要使用的。

3 个答案:

答案 0 :(得分:5)

首先,你永远不应该使用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):

请注意,我在此更改了基于integer_types的{​​{1}}定义,而不是版本测试。现在,您的代码兼容Python 2和3,以及任何其他没有NameError类型的假设Python构建。

答案 1 :(得分:4)

通常,如果我要在python中进行类型检查,我更愿意在可能的情况下检查抽象基类。在这种情况下,存在numbers.Integral可能很好地工作......

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

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


当然,这个答案(以及到目前为止提出的所有其他答案)都假设您实际上想要做同样的事情,如果数字是int a {{1} }。 任何想要根据它是否具有longint而做出不同的事情的代码看起来都很可怕而且尝试将其直接移植到python3.x是没有希望的,因为long根本没有存在使得代码路径实际上已经死亡。

答案 2 :(得分:0)

我喜欢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)