Бывает такое, что нам нужна только некоторая часть списка, например все элементы с 5 по 10, или все элементы с четными индексами. Подобное можно сделать с помощью срезов.
Срез задаётся как список[start:end:step]
, где из списка будут браться элементы с индексами от start
(включительно) до end
(не включительно) с шагом step
. Любое из значений start
, end
, step
можно опустить. В таком случае по умолчанию start
равен 0, end
равен длине списка, то есть индексу последнего элемента + 1, step
равен 1.
Cрезы и range
очень похожи набором параметров.
Срез a[::]
будет содержать просто весь список a
:
In [1]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[::])
Можно опустить и :
перед указанием шага, если его не указывать:
In [2]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[:])
Указываем до какого элемента выводить:
In [3]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[:5]) # то же самое, что и lst[:5:]
In [4]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[:0])
Или с какого элемента начинать:
In [5]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[2:])
In [6]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[2:5])
In [7]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[1:7:2])
In [8]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[::2])
Можно даже сделать отрицательный шаг, как в range
:
In [9]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[::-1])
С указанием начала срез с отрицательным шагом можно понимать как: "Начиная с элемента с индексом 2 идти в обратную сторону с шагом 1 до того, как список закончится".
In [10]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[2::-1])
Для отрицательного шага важно правильно указывать порядок начала и конца, и помнить, что левое число всегда включительно, правое - не включительно:
In [11]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
# Допустим, хотим элементы с индексами 1 и 2 в обратном порядке
print(lst[1:3:-1])
# Начиная с элемента с индексом 2 идти в обратную сторону с шагом 1
# до того, как встретим элемент с индексом 0 (0 не включительно)
print(lst[2:0:-1])
Срезы не изменяют текущий список, а создают копию. С помощью срезов можно решить проблему ссылочной реализации при изменении одного элемента списка:
In [12]:
a = [1, 2, 3, 4] # а - ссылка на список, каждый элемент списка это ссылки на объекты 1, 2, 3, 4
b = a # b - ссылка на тот же самый список
a[0] = -1 # Меняем элемент списка a
print("a =", a)
print("b =", b) # Значение b тоже поменялось!
print()
a = [1, 2, 3, 4]
b = a[:] # Создаём копию списка
a[0] = -1 # Меняем элемент списка a
print("a =", a)
print("b =", b) # Значение b не изменилось!
С помощью срезов можно, например, пропустить элемент списка с заданным индексом:
In [13]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
print(lst[:4] + lst[5:])
Или поменять местами две части списка:
In [14]:
lst = [1, 2, 3, 4, 5, 6, 7, 8]
swapped = lst[5:] + lst[:5] # поменять местами, начиная с элемента с индексом 5
print(swapped)
Срезы можно использовать не только для списков, но и для строк. Например, чтобы изменить третий символ строки, можно сделать так:
In [15]:
s = "long string"
s = s[:2] + "!" + s[3:]
print(s)