为什么six.py使用自定义类来查找MAXSIZE?

mu *_*u 無 5 python python-2.x python-3.x python-internals six

我正在浏览six.pydjango utils中的代码,对于非Jython实现,尝试为int找到MAXSIZE.现在,这样做的方式很有趣 - 不是在语句本身上捕获异常,而是将语句包装在__len__自定义类中的方法中.这样做的原因是什么?

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
Run Code Online (Sandbox Code Playgroud)

如果我没有错,同样可以缩短到下面,对吧?

try:
    1 << 31
except OverflowError:
    # 32-bit
    MAXSIZE = int((1 << 31) - 1)
else:
    # 64-bit
    MAXSIZE = int((1 << 63) - 1)
Run Code Online (Sandbox Code Playgroud)

Sin*_*ion 4

int在python3中是一种多语言类,可以表示机器整数以及大整数;int该功能取代了 python2 中和之间的区别long。在 python3 上,构造int(1 << n)永远不会抛出错误。

为了解决这个问题,六号使用了一个巧妙的技巧,迫使python 将一些东西塞进机器大小的 int 中。内置函数len总是尝试将 的返回值转换__len__为机器大小的值:

>>> 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

>>> 
Run Code Online (Sandbox Code Playgroud)

或者,在 Python 3 中,例外情况略有不同:

>>> len(Lengthy(1<<100))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: cannot fit 'int' into an index-sized integer
>>> 
Run Code Online (Sandbox Code Playgroud)