切片索引限制为0x7FFFFFFF

时间:2013-10-31 02:18:28

标签: python python-2.7 python-internals

我正在玩Python(2.7.4)中的切片:

class Foo():
    def __getitem__(self, key):
        # Single value
        if isinstance(key, (int,long)):
            return key

        # Slice
        if isinstance(key, slice):
            print 'key.start = 0x{0:X}   key.stop = 0x{1:X}'.format(key.start, key.stop)
            length = key.stop - key.start
            return str(length)

一切似乎都按预期工作:

>>> f = Foo()
>>>
>>> f[42]
42
>>>
>>> f[20:30]
key.start = 0x14   key.stop = 0x1E
'10'

除了切片索引似乎限于0x7FFFFFFF:

>>> f[0xFEDCBA98 : 0xFFFFFFFF]
key.start = 0x7FFFFFFF   key.stop = 0x7FFFFFFF
'0'
>>> f[0x80000000:0x90000000]
key.start = 0x7FFFFFFF   key.stop = 0x7FFFFFFF
'0'

为什么切片索引不会与常规long值相同的int整数提升?有没有解决方法呢?

2 个答案:

答案 0 :(得分:7)

我意识到这似乎是旧式课程的限制。 New-style classes(源自object的行为)符合预期:

class Foo(object):
   #...

结果:

>>> f = Foo()
>>>
>>> f[0x80000000:0x90000000]
key.start = 0x80000000   key.stop = 0x90000000
'268435456'
>>>
>>> f[0xFEDCBA98 : 0x1200000000]
key.start = 0xFEDCBA98   key.stop = 0x1200000000
'73033532776'
>>>

我没有在任何地方看到过这种情况。这特别令人困惑,因为这个限制不在slice类本身:

>>> s = slice(0xFEDCBA98, 0x1200000000)
>>>
>>> s
slice(4275878552L, 77309411328L, None)
>>>
>>> hex(s.start)
'0xfedcba98L'

答案 1 :(得分:7)

经过大量搜索,我找到了这个

在python 3.3中,切片的开始和结束类似于this

start = PyLong_FromSsize_t(istart);
...
end = PyLong_FromSsize_t(istop);

但是在2.7中它们被发现像this

start = PyInt_FromSsize_t(istart);
...
end = PyInt_FromSsize_t(istop);

在2.7中,PyInt_FromSsize_t最终使用long的大小,其中3.3 PyLong_FromSsize_t使用PyObject的大小。这就是为什么它在3.3而不是在2.7中工作正常。