Расставляем данные по полкам используя списки

Цикл for

Прежде чем мы поговорим про списки, давай сделаем жизнь немного удобнее с помощью цикла for. В задачах с циклами нам часто приходилось перебирать числа в определенном диапазоне, примерно вот так:

i = 5
while i < 15:
    print('^ ' * i)
    i += 1

Есть способ записать эту конструкцию лаконичней, используя цикл for.

# для всех значений i в диапазоне от 5 до 15
# правая граница не включается
for i in range(5, 15): 
    print('^ ' * i)

Если цикл while повторяется, пока верно его условие, то цикл for перебирает элементы в итерируемом множестве. Множество итерируемо, если его элементы можно перебрать по очереди (т.е. они упорядочены). Например буквы в строке имеют порядок (позиции), а значит их точно так же можно перебрать используя for.

for letter in "Илосос":
    print(letter * 5)

Результат:

ИИИИИ
ллллл
ооооо
ссссс
ооооо
ссссс

Что такое список?

Теперь вернемся к спискам...

Переменные - это просто отлично! Особенно в языках с динамической типизацией, таких, как питон. Можно взять любое значение и сохранить его в памяти. А потом взять его обратно, просто назвав имя.

Но что делать, если нужно сохранить много данных? Например, ежечасовую температуру во Владивостоке за 1995 год (чтобы потом посчитать отклонение от среднего)? Придется ведь создавать отдельную переменную для каждого значения, придумать имя, а затем вывести каждую из них отдельным print. Долго? Долго. Скучно? Еще как! А что делать, если мы в принципе заранее не знаем сколько данных нужно будет сохранить?

У этих проблем есть отличное решение - список! Чтобы понять что это, можно представить себе длинный коридор в гостинице с одноместными номерами. В каждой комнате живет значение, а на двери написан номер. Номера начинаются с 0. Количество номеров можно регулировать, на ходу достраивая новые номера в конец коридора или снося номера в любом месте. Но и номера тогда сдвигаются. Весь этаж гостиницы имеет свое имя, и этот этаж и есть список.

Другой пример, явно лучше - это поезд. У каждого вагона есть свой номер, причем у локомотива номер 0. В каждом вагоне едет одно значение. Вагоны можно убирать из состава, но их нумерация снова будет соответствовать порядковому номеру вагона. Также можно добавлять новые вагоны в конец. Пассажиров можно в любой момент менять по своему желанию. У поезда, в отличие от вагона, есть название. И да, этот поезд - и есть наш список.

Список - это множество значений в оперативной памяти. У списка есть имя, а у каждого его элемента есть номер. Номера элементов в списке начинаются с нуля.

И еще раз:

Номера элементов в списке начинаются с нуля!

Как работать со списками?

Как создать список? Есть два варианта - создать пустой список и потом заполнить его, либо сразу перечислить все его элементы.

Создание пустого списка:

names = []
print("Как звали гномов из сказки?")
for i in range(5):
    name = input()
    names.append(name) 

print(names)

А если перечисляем элементы сразу...

# знакомьтесь, это список и его зовут planets. В нем все планеты солнечной системы
planets = ['Меркурий', 'Венура', 'Земля', 'Марс', 'Юпитер', 'Сатурн', 'Уран', 'Нептун', 'Плутон']

Теперь продолжим работать с этим списком. Для начала, списки нужны нам, чтобы хранить сразу много элементов. Но как теперь к ним обращаться? Для этого используются квадратные скобочки, в них указывается номер нужного нам элемента.

print("Как называется первая планета от солнца?")
print(planets[0]) # первый элемент списка

print("А вторая?")
print(planets[1])

Чтобы случайно не обратиться к несуществующему элементу, нам полезно знать, сколько их всего.

print("Сколько всего планет в солнечной системе?")
print(len(planets)) # длина списка (также, как и строки)

print('-'*15)

А как обратиться к последнему элементу? Опять два варианта - либо вычислить его номер вручную (размер списка минус один), либо использовать отрицательную индексацию.

print("А как называется самая далекая планета?")
print(planets[len(planets) - 1]) # если первый элемент нулевой, то и последний - размер минус один

print("Как как?")
print(planets[-1]) # гораздо проще, на правда ли?

А как вывести список целиком или перебрать все его элементы по очереди? Пригодится for!

print("А можно перечислить все?")
print(planets)

print("А если в столбик?")
# читается как: для каждой планеты из планет
for planet in planets:
    print(planet)

print("А можно с номером?")
# можно, но чуть менее лаконично
for i in range(len(planets)):
    print(i, '-', planets[i]))

Кстати, а можно ли взять не отдельный элемент списка, а сразу несколько? Да, для этого используются срезы. В квадратный скобочках можно указать не только номер, но и дипазон. Полная форма среза выглядит как [От:До:Шаг]. Но ненужные параметры можно упускать.

print("Какие планеты в середине?")
print(planets[2:5])

print("Какие планеты за третьей?")
print(planets[3:])

print("Какие планеты до третьей?")
print(planets[:3])

print("Планеты с нечетными номерами?")
# со второй по последнюю с шагом два
print(planets[1::2])

print("Планеты с четными номерами?")
# со первой по последнюю с шагом два
print(planets[::2])

print("Планеты задом наперед?")
# от начала до конца с шагом -1
print(planets[::-1])

А что если элемент списка нужно поменять? Точно также как и получить элемент по номеру - через квадратные скобочки. А еще элементы можно удалять.

print("Кажется во второй планете ошибка, можно исправить?")
planets[1] = 'Венера' # меняем пассажира в первом вагоне
print(planets)

print("Погодите, Плутон - это не планета!")
del planets[8] # удаляем 9ый элемент списка
print(planets)

print("Мы нашли еще планету и назвали ее Блокчейний. Можете добавить?")
planets.append('Блокчейний') # добавляем в конец
print(planets)

print("Спасибо за экскурсию!")

Поиск и другие операции со списками

Иногда нам может понадобится что-то найти в списке. Это можно сделать разными способами.

backpack = ['фонарик', 'веревка', 'палатка', 'консервы', 'консервы']

print('Ты взял фонарик?')
if 'фонарик' in backpack:
    print('да')
else:
    print('ой, забыл')

print('А ножик не забыл?')
if 'нож' not in backpack:
    print('забыл')
else:
    print('нет, все на месте')

print('На каком месте палатка?')
print(backpack.index('палатка'))

print('А еды сколько?')
print(backpack.count('консервы'))

А еще может понадобится найти максимум и минимум, с ними тоже все просто:

results = [23, 120, 34, 56]

print('Каков самый большой результат?')
print(max(results))

print('А наименьший?')
print(min(results))

Если можно найти максимум и минимум, то можно пойти дальше - отсортировать список по возрастанию.

results = [23, 120, 34, 56]

results.sort()

print(results)

А еще списки можно складывать:

# можно складывать
print([1, 2] + ["А", "B"])
# [1, 2, 'А', 'B']

# и даже умножать
print(["Хех"] * 10)
# ['Хех', 'Хех', 'Хех', 'Хех', 'Хех', 'Хех', 'Хех', 'Хех', 'Хех', 'Хех']