range
range — неизменяемая последовательность целых чисел, которая вычисляет элементы по требованию и не хранит их в памяти:
print(list(range(5)))print(list(range(2, 8)))print(list(range(10, 0, -3)))print(list(range(0)))Форма range(stop), range(start, stop) или range(start, stop, step). Конечное значение не включается, step не может быть нулём.
Операции
range поддерживает те же операции, что и неизменяемые последовательности:
r = range(0, 100, 5)print(len(r))print(r[3])print(r[-1])print(r[2:5])print(15 in r)print(16 in r)print(r.index(25))print(r.count(25))print(r.start, r.stop, r.step)Проверка x in range(...) выполняется за O(1) даже для огромных диапазонов:
print(10 ** 15 in range(10 ** 18))Методы и атрибуты range
| Элемент | Описание |
|---|---|
start, stop, step | Параметры диапазона |
index(x) | Позиция значения, иначе ValueError |
count(x) | 0 или 1 |
Сравнение
print(range(3) == range(0, 3, 1))print(range(0) == range(5, 5))print(range(0, 5, 2) == range(0, 6, 2))Диапазоны сравниваются как последовательности значений.
Типичные применения
for i in range(3): print(i)for i in range(len("abc") - 1, -1, -1): print(i)evens = list(range(0, 11, 2))print(evens)print(sum(range(1, 101)))Для перебора элементов вместе с индексами предпочитайте enumerate, а не range(len(...)).
slice
Срез a[1:5:2] — это синтаксический сахар для объекта slice:
s = slice(1, 5, 2)data = list(range(10))print(data[s])print(data[1:5:2])print(s.start, s.stop, s.step)Объекты slice удобно хранить в переменных и переиспользовать:
FIRST_THREE = slice(None, 3)EVERY_SECOND = slice(None, None, 2)print("abcdefg"[FIRST_THREE])print([1, 2, 3, 4, 5][EVERY_SECOND])Метод slice.indices
s = slice(None, 100)print(s.indices(5))print(s.indices(10))Возвращает кортеж (start, stop, step) с учётом длины последовательности.
Правила срезов
- Конечный индекс не включается
- Отрицательные индексы считаются с конца
- Выход за границы не вызывает ошибку, срез просто усекается
- Отрицательный шаг идёт в обратную сторону
s = "abcdef"print(s[2:])print(s[:-1])print(s[-3:])print(s[1:100])print(s[::-1])print(s[4:1:-1])Результаты: cdef, abcde, def, bcdef, fedcba, edc.
Срезы и изменяемые последовательности
a = [0, 1, 2, 3, 4, 5]a[1:3] = [10, 20, 30]print(a)del a[::2]print(a)a[:0] = [-1, -2]print(a)Присваивание срезу заменяет участок последовательностью другой длины. Для расширенных срезов (с шагом) длина должна совпадать.
Поддержка в своих классах
Для поддержки срезов реализуйте __getitem__, принимающий int или slice:
class Squares: def __init__(self, n): self.n = n def __len__(self): return self.n def __getitem__(self, index): if isinstance(index, slice): return [self[i] for i in range(*index.indices(self.n))] if index < 0: index += self.n if not 0 <= index < self.n: raise IndexError(index) return index ** 2sq = Squares(10)print(sq[3])print(sq[2:6])print(sq[::3])Задания
- Выведите числа от 100 до 1 с шагом 7 и вычислите их сумму без цикла.
- Реализуйте класс-последовательность, поддерживающую срезы и отрицательные индексы.
- Разбейте список на блоки по
nэлементов через срезы иrange.
