Урок 25 Списки

list, методы списков

⏱ ~15 мин чтения· 📘 Базовый

Создание списков

Список — упорядоченная изменяемая коллекция:

# Пустой список (оба способа равноценны)
empty = []
another_empty = list()

# С элементами
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
nested = [[1, 2], [3, 4]]  # список списков

Индексация и срезы

Работает так же, как со строками:

nums = [10, 20, 30, 40, 50]

print(nums[0])     # 10
print(nums[-1])    # 50
print(nums[1:4])   # [20, 30, 40]
print(nums[::-1])  # [50, 40, 30, 20, 10]

# В отличие от строк, списки можно изменять
nums[0] = 100
print(nums)  # [100, 20, 30, 40, 50]

Методы списков

Основные методы для работы со списками:

nums = [1, 2, 3]

nums.append(4)        # [1, 2, 3, 4] — добавить в конец
nums.extend([5, 6])   # [1, 2, 3, 4, 5, 6] — расширить
nums.insert(1, 99)    # [1, 99, 2, 3, 4, 5, 6] — вставить по индексу
                      # insert(индекс, значение)
nums.remove(3)        # [1, 99, 2, 4, 5, 6] — удалить по значению
                      # удаляется первое найденное значение слева
print(nums.pop())     # 6 — удалить и вернуть последний
print(nums.pop(0))    # 1 — удалить и вернуть по индексу
nums.sort()           # [2, 4, 5, 99] — сортировка по возрастанию
nums.reverse()        # [99, 5, 4, 2] — разворот
print(nums.index(4))  # 2 — индекс элемента
print(nums.count(2))  # 1 — количество вхождений

nums.clear()          # [] — удалить все элементы

Если значения нет в списке, методы .remove(x) и .index(x) вызовут ошибку ValueError:

nums.remove(10)  # ValueError: list.remove(x): x not in list

Сортировку по убыванию можно задать аргументом reverse=True:

nums = [3, 1, 2]
nums.sort(reverse=True)  # [3, 2, 1]

Операторы со списками

Списки можно складывать, умножать и проверять на вхождение элементов:

a = [1, 2, 3]
b = [4, 5]

print(a + b)       # [1, 2, 3, 4, 5] — конкатенация
print(a * 3)       # [1, 2, 3, 1, 2, 3, 1, 2, 3] — повторение
print(a)           # [1, 2, 3] — исходный список не изменился

print(2 in a)      # True — элемент есть в списке
print(10 in a)     # False
print(10 not in a) # True — отрицание

+ и * создают новый список, не изменяя исходные.

Проверка вхождения in часто используется в условиях:

if "банан" in ["яблоко", "банан", "вишня"]:
    print("В корзине есть банан")

Оператор del удаляет элемент или срез по индексу. В отличие от .pop(), он удаляет элемент, не возвращая его:

nums = [10, 20, 30, 40, 50]
del nums[1]      # [10, 30, 40, 50] — удалить по индексу
del nums[1:3]    # [10, 50] — удалить срез

Функции len() и sorted()

Встроенная функция len() возвращает количество элементов в списке:

nums = [10, 20, 30, 40]
print(len(nums))  # 4
print(len([]))    # 0 — пустой список

len() работает с любыми коллекциями — не только со списками, но и со строками, кортежами, словарями.

sorted() возвращает новый отсортированный список, не изменяя исходный. В отличие от .sort(), который сортирует список на месте, sorted() можно применять к любому итерируемому объекту:

nums = [3, 1, 4, 1, 5]
new = sorted(nums)
print(new)   # [1, 1, 3, 4, 5] — отсортированный список
print(nums)  # [3, 1, 4, 1, 5] — исходный не изменился

Для списков чисел полезны встроенные функции sum(), min() и max():

scores = [5, 3, 9, 1, 7]
print(sum(scores))   # 25 — сумма всех элементов
print(min(scores))   # 1 — минимальный элемент
print(max(scores))   # 9 — максимальный элемент

Перебор списка и enumerate()

Цикл for проходит по элементам списка по порядку:

fruits = ["яблоко", "банан", "вишня"]

for fruit in fruits:
    print(fruit)
# яблоко
# банан
# вишня

Чтобы одновременно получить индекс и элемент, используют enumerate() — она возвращает пары (индекс, значение). Каждая пара — это кортеж, о которых подробнее в уроке 27:

for i, fruit in enumerate(fruits):
    print(i, fruit)
# 0 яблоко
# 1 банан
# 2 вишня

Счёт по умолчанию начинается с 0. Если нужно начинать с другого числа, передайте его вторым аргументом:

for i, fruit in enumerate(fruits, 1):
    print(f"{i}. {fruit}")
# 1. яблоко
# 2. банан
# 3. вишня

Копии и ссылки

Присваивание b = a не создаёт копию списка — обе переменные ссылаются на один и тот же объект. Поэтому изменения через b будут видны и в a:

a = [1, 2, 3]
b = a
b.append(4)
print(a)  # [1, 2, 3, 4] — изменился тот же список

Чтобы получить независимую копию, используют метод list.copy() или срез list[:]. Такая копия — поверхностная: список с простыми значениями полностью независим от оригинала, но вложенные списки в копии и оригинале остаются общими:

a = [1, 2, 3]
b = a.copy()
c = a[:]

b.append(4)
print(a)  # [1, 2, 3] — оригинал не изменился
print(b)  # [1, 2, 3, 4]

nested = [[1, 2], [3, 4]]
shallow = nested[:]
shallow[0].append(99)
print(nested)  # [[1, 2, 99], [3, 4]] — внутренний список общий