Ответы выше не обсуждают назначение срезов. Чтобы понять назначение срезов, полезно добавить еще одну концепцию к искусству ASCII:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
Slice position: 0 1 2 3 4 5 6
Index position: 0 1 2 3 4 5
>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
'P'
>>> p[5]
'n'
# Slicing gives lists
>>> p[0:1]
['P']
>>> p[0:2]
['P','y']
Одна эвристика заключается в том, что для среза от нуля до n подумайте: «ноль - это начало, начните с начала и возьмите n элементов в списке».
>>> p[5] # the last of six items, indexed from zero
'n'
>>> p[0:5] # does NOT include the last item!
['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
['P','y','t','h','o','n']
Другая эвристика: «для любого среза замените начало на ноль, примените предыдущую эвристику, чтобы получить конец списка, а затем сосчитайте первое число обратно, чтобы отрезать элементы от начала»
>>> p[0:4] # Start at the beginning and count out 4 items
['P','y','t','h']
>>> p[1:4] # Take one item off the front
['y','t','h']
>>> p[2:4] # Take two items off the front
['t','h']
# etc.
Первое правило назначения слайсов состоит в том, что поскольку срез возвращает список, назначение слайсов требует список (или другой итеративный):
>>> p[2:3]
['t']
>>> p[2:3] = ['T']
>>> p
['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
Второе правило назначения слайсов, которое вы также можете видеть выше, заключается в том, что любая часть списка, возвращаемая при индексации слайсов, это та же часть, которая изменяется при назначении слайсов:
>>> p[2:4]
['T','h']
>>> p[2:4] = ['t','r']
>>> p
['P','y','t','r','o','n']
Третье правило назначения слайсов состоит в том, что назначенный список (повторяемый) не должен иметь одинаковую длину; Индексированный фрагмент просто вырезается и заменяется массово тем, что ему назначено:
>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
['P','y','s','p','a','m','o','n']
Самая хитрая часть, к которой нужно привыкнуть, - это назначение пустым слайсам. Используя эвристику 1 и 2, легко обойти , индексировать пустой фрагмент:
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
И затем, как только вы это увидели, назначение среза пустому срезу также имеет смысл:
>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
['P','y','t','h','x','y','o','n'] # The result is longer still
Обратите внимание, что, поскольку мы не меняем второе число среза (4), вставленные элементы всегда располагаются прямо напротив «o», даже когда мы назначаем пустой срез. Таким образом, позиция для назначения пустых срезов является логическим расширением позиций для непустых назначений срезов.
Немного резервного копирования, что произойдет, если вы продолжите нашу процессию подсчета начала среза?
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
С нарезкой, как только вы закончите, вы закончите; это не начинает разрезать назад. В Python вы не получите отрицательных шагов, если вы явно не попросите их, используя отрицательное число.
>>> p[5:3:-1]
['n','o']
Есть некоторые странные последствия для правила «как только вы закончите, вы закончите»:
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
>>> p[6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
На самом деле, по сравнению с индексацией, нарезка Python причудливо защищена от ошибок:
>>> p[100:200]
[]
>>> p[int(2e99):int(1e99)]
[]
Иногда это может пригодиться, но может привести к несколько странному поведению:
>>> p
['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']
В зависимости от вашего приложения, это может ... или не может ... быть тем, на что вы надеялись!
<Ч />
Ниже приведен текст моего первоначального ответа. Это было полезно для многих людей, поэтому я не хотел его удалять.
>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]
Это также может прояснить разницу между нарезкой и индексацией.