lst = [1,2,3]
print(lst[5:]) # []

Я ожидаю, что приведенный выше код выдает ошибку индекса. Почему этот код не выдает никаких ошибок? Есть какие-то изменения в версии Python 3.10 или это есть и в предыдущих версиях?

0
codester_09 4 Окт 2022 в 21:46
5
Так было всегда, и это задокументированное поведение . В примечании о срезах говорится: «Срез s от i до j определяется как последовательность элементов с индексом k, такая что i <= k < j. Если i или j больше, чем len(s), используйте len(s ). Если i опущено или None, используйте 0. Если j опущено или None, используйте len(s). Если i больше или равно j, срез пуст." - так что ничего, что могло бы вызвать ошибку.
 – 
Thierry Lathuille
4 Окт 2022 в 21:49
Что это значит в документах? "That index will continue to march forward (or backward) even if the underlying sequence is mutated. The iterator terminates only when an IndexError or a StopIteration is encountered (or when the index drops below zero)."
 – 
codester_09
4 Окт 2022 в 21:52

1 ответ

Это всегда было гранью нарезки Python:

>>> ls = [1,2,3]
>>> ls[5:]
[]
>>> ls[:5]
[1, 2, 3]

Поскольку список недостаточно длинный, срез становится пустым, когда вы указываете начало после конца.

Чтобы ответить на ваш дополнительный вопрос: если у вас есть список, такой как тот, который определен выше, и вы повторяете его, как показано ниже, и во время этой итерации вы делаете что-то, чтобы изменить список, итератор будет продолжать работать, как если бы вы не не сделал изменение.

ls = [1,2,3]
for x in ls:
    del ls[2]

Это вызовет ошибку:

>>> ls = [1,2,3]
>>> for x in ls:
...     del ls[2]
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
IndexError: list assignment index out of range

Это связано с тем, что когда итератор достигает значения 2, ваш список сжимается, но итератор соответственно не сжимается.

3
Nathaniel Ford 4 Окт 2022 в 22:01
@codester_09: Насколько я знаю, это всегда так работало.
 – 
dan04
4 Окт 2022 в 21:50
1
Это была одна из первоначальных причин, по которой Python считался «простым» в использовании — способность выполнять нарезку массива естественным образом, не вызывая случайных ошибок.
 – 
Nathaniel Ford
4 Окт 2022 в 21:54
Это несколько другой вопрос: это означает, что если вы установите список ls = [1,2,3], а затем начнете перебирать его: for i in ls, скажем, даже если вы сделали что-то вроде удаления первого элемента, итератор продолжал бы идти. Это приводит к странному поведению, поэтому вам не следует этого делать.
 – 
Nathaniel Ford
4 Окт 2022 в 21:56
Я пытался объяснить - надеюсь понятно, но это это отдельный вопрос, чем то, с чего вы начали.
 – 
Nathaniel Ford
4 Окт 2022 в 22:02