【问题标题】:Slice indices limited to 0x7FFFFFFF切片索引限制为 0x7FFFFFFF
【发布时间】:2013-10-31 02:18:27
【问题描述】:

我正在使用 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'

为什么切片索引不像常规 int 值那样受到相同的 long 整数提升?有什么解决方法吗?

【问题讨论】:

  • 有趣。我使用 Python 3.3.2 得到了正确的结果
  • @aIKid 谢谢 - 我没有立即访问 Python 3。这是有道理的,因为 Python 3 只有新样式的类......请参阅 my answer

标签: python python-2.7 python-internals


【解决方案1】:

我意识到这似乎是旧式类的限制。 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'

【讨论】:

    【解决方案2】:

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

    在 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 中运行良好的原因。

    【讨论】:

    • 非常有趣!我想剩下的问题是,为什么它在 2.7 中适用于新式对象(源自object)而不是旧式?我假设差异会导致在引擎盖下使用不同的类型,这可能是出于相同的原因。如果有机会,我可能会深入研究。感谢您的出色研究!
    猜你喜欢
    • 2021-12-31
    • 2018-07-29
    • 2014-12-24
    • 1970-01-01
    • 2021-08-25
    • 2017-03-16
    • 1970-01-01
    • 2015-03-16
    • 2018-10-31
    相关资源
    最近更新 更多