I was going through the code for six.py
in the django utils, which, for non Jython implementations, tries, to find the MAXSIZE for the int. Now, the way this is done is interesting - instead of catching an exception on the statement itself, the statement is wrapped within a __len__
method in a custom class. What may be the reason(s) to do so?
class X(object):
def __len__(self):
return 1 << 31
try:
len(X())
except OverflowError:
# 32-bit
MAXSIZE = int((1 << 31) - 1)
else:
# 64-bit
MAXSIZE = int((1 << 63) - 1)
del X
If I'm not wrong, the same could have been shortened to the below as well, right?
try:
1 << 31
except OverflowError:
# 32-bit
MAXSIZE = int((1 << 31) - 1)
else:
# 64-bit
MAXSIZE = int((1 << 63) - 1)
int
in python3 is a poly-glot sort of class that can represent machine ints as well as big-ints; a feature that superseedes the distinction between int
and long
in python2. On python3, the construction int(1 << n)
never throws an error.
So to solve that, six is using a neat trick that forces python to cram something into a machine sized int. The len
builtin always trys to convert the return value of __len__
into a machine sized thing:
>>> class Lengthy(object):
... def __init__(self, x):
... self.x = x
... def __len__(self):
... return self.x
...
>>> int(1<<100)
1267650600228229401496703205376L
>>> type(int(1<<100))
<type 'long'>
>>> len(Lengthy(1<<100))
Traceback (most recent call last):
File "<ipython-input-6-6b1b77348950>", line 1, in <module>
len(Lengthy(1<<100))
OverflowError: long int too large to convert to int
>>>
or, in Python 3, the exception is slightly different:
>>> len(Lengthy(1<<100))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot fit 'int' into an index-sized integer
>>>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With