I've got some code written with python 2.7.x that I'm trying to make compatible with python 3.x. I've resolved most of the issues converting the code to work under both versions, but wanted advice dealing with int/long types.
Much of the work to unify int and long types occurred in much earlier (2.4.x) releases and the distinction was completely removed in V3 ( The '1L' format is no longer valid). At the same time the types module was modified to remove references to types already built-in and the redundant 'long' built-in type was removed.
So under V2.x I still need to support code like:
if type(var) == int or type(var) == long :
do_stuff
or
if type(var) == int :
do_int_stuff
elif type(var) == long :
do_long_stuff
But with V3 there is no built-in class for long, and no need to do_long_stuff that's different from normal do_int_stuff. The built-in class type variable 'long' is no longer defined, so this code would fail with a NameError.
One easy solution is to define 'long' as None or some other nonsense type under v3, understanding type(var) != long for any var. The long built-in class type defined under v2.x would remain the same.
if sys.version_info.major == 3 :
long = None
Is None the best value to use? In my case setting 'long = int' isn't what I want to use.
First of all, you should never use type(obj) == type_obj
; use the isinstance()
function , always. Rarely do you need to ignore subclasses, and if you do need to ignore subclasses you can use type(obj) is type_obj
instead.
isinstance()
can take a tuple of types:
isinstance(obj, (int, long))
which then allows you to use a variable:
try:
integer_types = (int, long)
except NameError:
integer_types = int
if isinstance(obj, integer_types):
Note that I swapped out the integer_types
definition based on a NameError
here, not on a version test. Now your code is compatible with both Python 2 and 3, as well as with any other hypothetical Python build where there is no long
type.
Generally, if I'm going to do type checking in python, I prefer to check against an abstract base class where possible. In this case, there exists numbers.Integral
which might work nicely...
>>> import numbers
>>> isinstance(1, numbers.Integral)
True
>>> isinstance(1L, numbers.Integral)
True
>>> isinstance(1., numbers.Integral)
False
This should work on both python2.x and python3.x.
Of course, this answer (and all the others proposed so far) assume that you actually want to do the same thing if the number is an int
or a long
. Any code which wants to do something different depending on whether it has an int
or long
seems scary and it is hopeless to try to port that directly to python3.x as long
simply does not exist making that codepath is effectively dead.
I like Martijn's answer, but would wrap it like
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
which you can use like
if is_int(var):
do_something(var)
or
if is_long(var):
do_long_stuff(var)
elif is_int(var):
do_int_stuff(var)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.