Вот как я учу новичков ломтикам:
Понимание разницы между индексированием и нарезкой:
В Wiki Python есть удивительная картинка, которая четко различает индексирование и нарезку.
![enter image description here](https://i.stack.imgur.com/o99aU.png)
Это список из 6 элементов. Чтобы лучше понять нарезку, рассмотрите этот список как набор из шести блоков, помещенных вместе. В каждой коробке есть алфавит.
Индексирование похоже на работу с содержимым коробки. Вы можете проверить содержимое любого ящика. Но Вы не можете проверить содержимое нескольких ящиков одновременно. Вы даже можете заменить содержимое коробки. Но Вы не можете поместить 2 шара в 1 коробку или заменить 2 шара одновременно.
In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']
In [124]: alpha[0]
Out[124]: 'a'
In [127]: alpha[0] = 'A'
In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']
In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]
TypeError: list indices must be integers, not tuple
Нарезка подобна работе с самими коробками. Вы можете забрать первую коробку и поставить ее на другой стол. Чтобы поднять коробку, вам нужно знать только положение начала и конца коробки.
Вы можете даже забрать первые 3 ящика или последние 2 ящика или все ящики между 1 и 4. Таким образом, Вы можете выбрать любой набор ящиков, если знаете начало и конец. Эти позиции называются стартовой и стоповой позициями.
Интересно то, что вы можете заменить несколько ящиков одновременно. Также Вы можете разместить несколько ящиков в любом месте.
In [130]: alpha[0:1]
Out[130]: ['A']
In [131]: alpha[0:1] = 'a'
In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']
In [133]: alpha[0:2] = ['A', 'B']
In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']
In [135]: alpha[2:2] = ['x', 'xx']
In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']
Нарезка с шагом:
До сих пор Вы постоянно выбирали ящики. Но иногда вам нужно забрать дискретно. Например, вы можете забрать каждую вторую коробку. Вы можете даже забрать каждую третью коробку с конца. Это значение называется размером шага. Это представляет собой разрыв между вашими последовательными пикапами. Размер шага должен быть положительным, если вы выбираете поля от начала до конца и наоборот.
In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [142]: alpha[1:5:2]
Out[142]: ['b', 'd']
In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']
In [144]: alpha[1:5:-2]
Out[144]: []
In [145]: alpha[-1:-5:2]
Out[145]: []
Как Python вычисляет недостающие параметры:
При разрезании, если вы пропускаете какой-либо параметр, Python пытается выяснить это автоматически.
Если вы проверите исходный код CPython, вы найдете функцию PySlice_GetIndicesEx, которая вычисляет индексы для среза для любых заданных параметров. Вот логический эквивалентный код в Python.
Эта функция принимает объект Python и необязательные параметры для нарезки и возвращает начальный, конечный, шаг и длину среза для запрошенного среза.
def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):
length = len(obj)
if step is None:
step = 1
if step == 0:
raise Exception("Step cannot be zero.")
if start is None:
start = 0 if step > 0 else length - 1
else:
if start < 0:
start += length
if start < 0:
start = 0 if step > 0 else -1
if start >= length:
start = length if step > 0 else length - 1
if stop is None:
stop = length if step > 0 else -1
else:
if stop < 0:
stop += length
if stop < 0:
stop = 0 if step > 0 else -1
if stop >= length:
stop = length if step > 0 else length - 1
if (step < 0 and stop >= start) or (step > 0 and start >= stop):
slice_length = 0
elif step < 0:
slice_length = (stop - start + 1)/(step) + 1
else:
slice_length = (stop - start - 1)/(step) + 1
return (start, stop, step, slice_length)
Это интеллект, который присутствует за кусочками. Поскольку в Python есть встроенная функция, называемая slice, вы можете передать некоторые параметры и проверить, насколько разумно он рассчитывает отсутствующие параметры.
In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [22]: s = slice(None, None, None)
In [23]: s
Out[23]: slice(None, None, None)
In [24]: s.indices(len(alpha))
Out[24]: (0, 6, 1)
In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]
In [26]: s = slice(None, None, -1)
In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]
In [28]: s = slice(None, 3, -1)
In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]
Примечание: Это сообщение изначально написано в моем блоге http://www.avilpage.com/2015/03/a-slice-of-python-intelligence-behind.html