I'm playing with slices in 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)
Everything seems to work as expected:
>>> f = Foo()
>>>
>>> f[42]
42
>>>
>>> f[20:30]
key.start = 0x14 key.stop = 0x1E
'10'
Except it seems that the slice indices are limited to 0x7FFFFFFF:
>>> f[0xFEDCBA98 : 0xFFFFFFFF]
key.start = 0x7FFFFFFF key.stop = 0x7FFFFFFF
'0'
>>> f[0x80000000:0x90000000]
key.start = 0x7FFFFFFF key.stop = 0x7FFFFFFF
'0'
Why are slice indices not subject to the same long
integer promotion as regular int
values? Is there any workaround for this?
I've realized that this appears to be a limitation of old-style classes. New-style classes (ones that derive from object
) behave as expected:
class Foo(object):
#...
Results:
>>> f = Foo()
>>>
>>> f[0x80000000:0x90000000]
key.start = 0x80000000 key.stop = 0x90000000
'268435456'
>>>
>>> f[0xFEDCBA98 : 0x1200000000]
key.start = 0xFEDCBA98 key.stop = 0x1200000000
'73033532776'
>>>
I haven't seen this documented anywhere. It's especially confusing, since this limitation is not in the slice
class itself:
>>> s = slice(0xFEDCBA98, 0x1200000000)
>>>
>>> s
slice(4275878552L, 77309411328L, None)
>>>
>>> hex(s.start)
'0xfedcba98L'
After a lot of searching I found this
In python 3.3, the slice start and end are found like this
start = PyLong_FromSsize_t(istart);
...
end = PyLong_FromSsize_t(istop);
but in 2.7 they are found like this
start = PyInt_FromSsize_t(istart);
...
end = PyInt_FromSsize_t(istop);
In 2.7, PyInt_FromSsize_t
ultimately uses the size of long
where as in 3.3, PyLong_FromSsize_t
uses the size of PyObject
. That is why it works fine in 3.3 and not in 2.7.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With