1

在 Python 3 中,我有一个类表示值的范围 [x,y] 并计算该范围的长度。

如果长度太大,我不确定如何在类本身中捕获 OverflowError异常。它仅在使用类实例的外部代码中引发......

class ValRange:
    val_min = None
    val_max = None
    range_len = 0

    def __init__(self, val_min, val_max):
        self.val_min = val_min
        self.val_max = val_max

    def __len__(self):
        if (self.val_min is not None and
             self.val_max is not None):
            length = 0
            try:
                length = int(self.val_max) - int(self.val_min) + 1
            except OverflowError as e:
                # Somehow no exception is caught here...
                print('OverflowError...')
                length = 10**5  # arbitrarily large number
            except Exception as e:
                print(e)
            if length > 0:
                self.range_len = length
        return self.range_len


import traceback
import uuid
x = uuid.UUID('00000000-cb9d-4a99-994d-53a499f260b3')
y = uuid.UUID('ea205f99-0564-4aa0-84c3-1b99fcd679fd')
r = ValRange(x, y)
try:
    print(len(r))
except:
    # The exception is caught in this outer code and not in the class itself. Why?
    print(traceback.format_exc())

# The following, which is equivalent to the operations in the 
# code above, will work. 
a = int(y) - int(x) + 1
print(a)

这是执行时发生的情况:

Traceback (most recent call last):
  File "/home/rira/bugs/overflow.py", line 35, in <module>
    print(len(r))
OverflowError: cannot fit 'int' into an index-sized integer

311207443402617699746040548788952897867
4

1 回答 1

2

那是因为OverflowError在你的魔法方法中不会出现__len__()- Python 完全能够处理比这更大的整数 - 但在 CPythonlen()中,它本身被实现为PyObject_Size()返回 a Py_ssize_t,它仅限于2^31-1(32 位)或2^63-1(64 位)因此,当您的__len__()结果被强制执行时,就会发生溢出。

您可以在返回结果之前进行预检查,以确保在溢出发生之前捕获它,例如:

def __len__(self):
    if (self.val_min is not None and self.val_max is not None):
        length = int(self.val_max) - int(self.val_min) + 1
        if length > sys.maxsize:
            print('OverflowError...')
            length = 10**5  # arbitrarily large number
        self.range_len = length
    return self.range_len
于 2018-05-16T09:38:39.857 回答