Питон C код, который обрабатывает нарезка для объектов, которые реализуют sq_slice
слот, не может обрабатывать любые целые числа над Py_ssize_t
(== sys.maxsize
). Слот sq_slice
представляет собой эквивалент C-API специального метода __getslice__
.
Для двухэлементного среза Python 2 использует один из SLICE+*
opcodes; затем обрабатывается apply_slice()
function. Это использует _PyEval_SliceIndex
function для преобразования индексных объектов Python (int
, long
или чего-либо, реализующего __index__
method) в целое число Py_ssize_t
. Метод имеет следующий комментарий:
/* Extract a slice index from a PyInt or PyLong or an object with the
nb_index slot defined, and store in *pi.
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
Return 0 on error, 1 on success.
*/
Это означает, что любой нарезка в Python 2 с использованием синтаксиса 2-значения ограничивается значениями в диапазоне sys.maxsize
при условии слота sq_slice
.
нарезка, используя форму на три значения (item[start:stop:stride]
) использует вместо BUILD_SLICE
opcode (с последующим BINARY_SUBSCR
), и это создает вместо slice()
object без ограничения, чтобы sys.maxsize
.
Если объект не реализует sq_slice()
слота (поэтому нет __getslice__
не присутствует) функция apply_slice()
также падает обратно с использованием slice()
объекта.
Что касается этой детали реализации или ее части: Slicings expression documentation различает simple_slicing
и extended_slicing
; первая только разрешает форму short_slice
. Для простого нарезания индексы должны быть простые целые числа:
Нижняя и верхняя граница выражения, если таковые имеются, должны вычисляться простых чисел; значения по умолчанию равны нулю и sys.maxint
, соответственно.
Это предполагает что Python 2 язык ограничивает индексы для sys.maxint
значений, запрещая длинные целые числа. В Python 3 простой срез был вырезан из всего языка.
Если ваш код должен поддерживать нарезку со значениями за sys.maxsize
и вы должны наследовать от типа, который реализует __getslice__
тогда ваши варианты для:
slice()
объекты могут обрабатывать long
целые просто отлично; однако slice.indices()
method не может справиться с длиной более sys.maxsize
еще:
>>> import sys
>>> s = slice(0, sys.maxsize + 1)
>>> s
slice(0, 9223372036854775808L, None)
>>> s.stop
9223372036854775808L
>>> s.indices(sys.maxsize + 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot fit 'long' into an index-sized integer
Должен сказать: «почему да, я хотел бы 2^64 ломтиков этого прекрасного картофеля». Серьезно, хотя, мне очень жаль, что у меня не было ответа – inspectorG4dget
Это один кусочек .. и это будет так же, как и с меньшим фрагментом, например 'maxint-2: maxint + 2' :) – wim