8

我在 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?有什么解决方法吗?

4

2 回答 2

7

我意识到这似乎是旧式类的限制。新型类(派生自 的类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'
于 2013-10-31T02:28:09.553 回答
7

经过大量搜索,我发现了这个

在python 3.3中,切片开始和结束是这样找到

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

但在 2.7 中,它们是这样被发现

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

在 2.7 中,PyInt_FromSsize_t最终使用longwhere 的大小,如 3.3 中一样,PyLong_FromSsize_t使用PyObject. 这就是为什么它在 3.3 而不是 2.7 中运行良好的原因。

于 2013-10-31T04:05:18.013 回答