+---------------------------+
|.-------------------------.|
|| kee_reel@blog:~$ cd     ||
|| c  c++  python  linux   ||
|| opengl  sql  networks   ||
||                         ||
||                 обо_мне ||
|.-------------------------.|
+-::---------------------::-+
.---------------------------.
 // /oooooooooooooooooooooo\\ \\ 
 // /oooooooooooooooooooooooo\\ \\ 
//-------------------------------\\
\\-------------------------------//

◀ Переменные и операции с ними Условия ▶

Python. Контейнеры

Время чтения: 8 мин

Контейнеры это незаменимый инструмент, при работе с наборами данных – давай их изучим. Существуют следующие типы контейнеров:

  • Списки
  • Кортежи
  • Словари

Списки

Зачастую, тебе не хватает переменной, чтобы вместить все данные – например, тебе нужно посчитать среднюю оценку для всей группы в университете по какому-то предмету (человек 25, например). Ты мог бы создать переменные (“student_1”, “student_2”, “student_3” и так далее), но это была бы очень монотонная и занудная работа.

К счастью разработчики очень ленивые, и давно придумали решение этой проблемы – список (list).

Создание

Создание списка выглядит вот так:

student_marks = [4, 5, 3, 3, 4, 5, 5, 3, 2, 5]

Также, ты можешь создать список пустым, чтобы потом его наполнить:

student_marks = []

В списке могут содержаться значения любых типов (даже другие списки):

student_marks = [1, '2', 'Three', [3, 11.2]]

student_marks это переменная – получается, что в переменных могут храниться не только обычные типы (числа и строки), но и списки, и много чего ещё. Это как раз и является проявлением динамической типизации, про которую я говорил во вводной статье. Вот мощная статья, если хочешь глубже понять что такое динамическая типизация.

Вывод значений

Чтобы вывести значения списка, можно просто передать его в print():

student_marks = [2, 3, 4, 5]
print(student_marks)
# Вывод будет такой:
# [2, 3, 4, 5]

Наполнение

После того, как список создан, в него можно добавлять новые элементы:

student_marks.append(4)

Можно вставлять в произвольное место в массиве (тут используется индекс – про него будет сказано ниже):

# 2 - индекс, куда надо вставить
# 4 - значение
student_marks.insert(2, 4)
# Так можно вставить в начало списка
student_marks.insert(0, 4)

А также можно добавлять в конец элементы других списков:

another_marks = [2, 3, 5]
student_marks.extend(another_marks)
# Или так
student_marks += another_marks

Функции для работы со списками

В Python существуют встроенные функции для работы со списками:

  • sum(твой-список) – сумма элементов списка
  • len(твой-список) – количество элементов списка
  • sorted(твой-список) – создать новый список, отсортированный по возрастанию

Вернёмся к задаче поиска средней оценки по группе. Вот так может выглядеть решение:

student_marks = [4, 5, 3, 3, 4, 5, 5, 3, 2, 5]
average_mark = sum(student_marks) / len(student_marks)
print(average_mark)

А что, если мы захотим достать самую высокую оценку, и самую низкую оценку?

Нууу, сначала мы отсортируем список:

student_marks = [3, 2, 3, 5, 4, 5]
student_marks = sorted(student_marks)

По умолчанию списки сортируются по возрастанию. Если нужно отсортирвать его по убыванию, то надо вызвать эту функцию так:

student_marks = sorted(student_marks, reverse=True)

Мы указали опциональный параметр функции – мы дойдём до этого в статье по функциям.

А теперь надо достать самую низкую (в начале списка), и самую высокую оценку (в конце списка). Чтобы понять как это сделать, надо сначала объяснить эту шутку: “Ты спросила на каком месте у меня работа. Я сказал, что на первом. Ты ушла, хлопнув дверью, так и не узнав, что ты у меня на нулевом”.

Индексы списка

Индексы списка

В то время, как нормальные люди считают порядковый номер элемента (первый, второй, третий…) – программисты считают смещение от первого элемента списка (на ноль, на один, на два).

Смещение от первого элемента называется индекс.

То есть чтобы получить первый элемент списка, нужно взять элемент по индексу 0:

print(student_marks[0]) # 2

А чтобы взять последний элемент, нужно взять элемент по индексу (количество элементов)-1, потому что мы начали считать с 0:

print(student_marks[len(student_marks) - 1]) # 5

Внимание! Следи чтобы индекс не выходил за пределы списка – это приведёт к ошибке при исполнении программы:

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

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

student_mark[1] = 5 # Заменили значение второго элемента на 5

Если указывать отрицательное значение, то индекс будет считаться с конца:

student_mark[-1] = 2 # Заменили значение последнего элемента на 2
student_mark[-2] = 5 # Заменили значение второго с конца элемента на 5

На самом деле индексация в списках устроена несколько иначе – здесь можно почитать немного теории (а потом там идёт реализация на C++).

Слайсы

Ты можешь “разрезать” список на более маленькие списки с помощью слайсов (можно перевести как ломтик, кусочек, отрезанная часть).

Исходный массив:

student_marks = [5, 3, 2, 4, 3, 5]
  • При задании слайса, ты указываешь индекс элемента, “от” которого начинается слайс, и индекс элемента, “до” которого нужно сделать слайс
student_marks[0:3] # [5, 3, 2]
  • Если индекс “от” не указан, то будет взят слайс от начала списка до индекса “до”
student_marks[:2] # [5, 3]
  • Если не указан индекс “до” то будет взят слайс от индекса “от” до последнего элемента списка
student_marks[1:] # [3, 2, 4, 3, 5]
  • Если в слайсе не указаны границы, то слайс будет таким же, как список
student_marks[:] # [5, 3, 2, 4, 3, 5]

Задание на закрепление

Создай список со значениями плотности населения (человек на квадратный километр) в 7 самых больших странах мира:

  • Россия: 8,56
  • Канада: 3,5
  • Китай: 139
  • США: 32
  • Бразилия: 23,6
  • Австралия: 2,8
  • Индия: 357

Задания:

  • Вычисли среднюю плотность населения по этим странам
  • Выведи самую низкую плотность
  • Выведи самую высокую плотность
  • Выведи список из 3 самых больших значений плотности (это про слайсы)

Кортежи

Кортеж (tuple) – это список, который нельзя изменять. Кортеж более эффективно использует память, поэтому его лучше использовать, когда у тебя есть наборы значений, которые точно не будут меняться (например кортеж, в котором перечислены планеты Солнечной системы или дни недели).

Пример создания кортежа:

days_of_week = ('Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье')

В кортеже также могут содержаться значения любых типов:

some_tuple = ('1', 2, [3, 4], 5.5)

Значения кортежа можно доставать через индекс, но перезаписывать их нельзя:

x = (1, 2, 3)
x[1] # 2
x[1] = -2 # ОШИБКА

Так как ты не можешь изменять кортеж, функции добавления элемента в конец (append) и добавления списка в конец (extend) использовать нельзя – в остальном поведение такое же как и у списков (индексы, слайсы и функции для работы со списками).

Словари

Словарь (dict) – это список, в котором хранятся пары ключ-значение. Ключ при этом должен быть уникальным и неизменяемым.

На самом деле словари в Python это хэш-таблицы – в них ОЧЕНЬ быстро происходит поиск значений. Вот про них на русском (там мало информации) и на английском (отличная статья).

Создание

Словарь создаётся так:

students = {
	'Иванов Иван Иванович': 4,
	'Сергеев Сергей Сергеевич': 3,
	'Максимов Максим Максимович': 5,
}

Также ключом может быть число (например уникальный ID пользователя), а значением вообще список:

ids = {
	102: [2, 3, 4],
	103: [3],
	105: [5, 4],
}

Благодаря свойству неизменности, кортежи тоже могут быть ключами, наравне с числами и строками. Например:

numbers = {
	('One', 1) : 'Un',
	('Two', 2) : 'Deux',
	('Three', 3) : 'Trois'
}

Или другой словарь:

# Ключ - имя, значение - словарь {ключ - предмет, значение - оценка}
students = {
	'Иванов Иван Иванович': {
		'Основы Python': 4,
		'Философия': 4,
	},
	'Сергеев Сергей Сергеевич': {
		'Основы Python': 3,
		'Философия': 5,
	},
	'Максимов Максим Максимович': {
		'Основы Python': 5,
		'Философия': 3,
	},
}

Также в словаре могут быть значения разных типов (это редко пригождается):

some_dict = {
	1: '1',
	'1': 1,
	(3, '1'): [3, 1, '1']
}

Как можно заметить, словари уже позволяют описывать довольно сложные наборы данных, в отличии от всего, что мы ранее рассматривали.

Вывод значений

Чтобы вывести значения словаря, можно просто передать его в print():

students = {
	'Иванов Иван Иванович': {
		'Основы Python': 4,
		'Философия': 4,
	}
}
print(students)
# Вывод будет такой:
# {'Иванов Иван Иванович': {'Основы Python': 4, 'Философия': 4}}

Получение значения по ключу

Так как ключ в словаре является уникальным, мы всегда можем получить из словаря нужное значение, зная ключ. Получение значения по ключу выглядит так же, как получение значения из списка по индексу – лишь с той разнцей, что мы передаём ключ:

print(students['Иванов Иван Иванович'])
# Выведет:
# {'Основы Python': 4, 'Философия': 4}

Добавление значения в словарь

Чтобы добавить в словарь новое значение, необходимо указать нужный ключ:

# Записываем оценки по предметам для студента
students['Семёнов Семён Семёнович'] = {'Основы Python': 3, 'Философия': 3}

Если ты укажешь уже существующий в словаре ключ, то ты перезапишешь старое значение по этому ключу.

Функции для работы со словарями

Ты можешь использовать следующие функции, для работы со словарями:

  • len(твой-список) – количество элементов словаря
  • list(твой-список.keys()) – получить список ключей словаря
  • list(твой-список.values()) – получить список значений словаря
  • list(твой-список.items()) – получить список пар ключ-значение словаря

Получение списка ключей, значений и пар ключ-значение обёрнуто в list() из-за того, что функции возвращают не “чистые” списки, а нечто другое. Пока что давай опустим что это такое, и просто используем функции как я написал.

Вот примеры использования:

students = {
	'Иванов Иван Иванович': 4,
	'Сергеев Сергей Сергеевич': 3,
	'Максимов Максим Максимович': 5,
}
len(students) # 3
list(students.keys()) # ['Иванов Иван Иванович', 'Сергеев Сергей Сергеевич', 'Максимов Максим Максимович']
list(students.values()) # [4, 3, 5]
# Обрати внимание, что каждая пара ключ-значение это кортеж из двух элементов -- ключа и значения.
list(students.items()) # [('Иванов Иван Иванович', 4), ('Сергеев Сергей Сергеевич', 3), ('Максимов Максим Максимович', 5)]

Задание на закрепление

Создай словарь, где ключом является название планеты, а значением дистанция до Солнца в километрах:

  • Меркурий: 57910006
  • Венера: 108199995
  • Земля: 149599951
  • Марс: 227939920
  • Юпитер: 778330257
  • Сатурн: 1429400028
  • Уран: 2870989228
  • Нептун: 4504299579

Задания:

  • Вычисли среднее расстояние до Солнца, учитывая все планеты
  • Выведи отсортированный список названий всех планет (функция sorted() умеет сортировать не только числа)
  • Вычисли во сколько раз Нептун дальше от Солнца, чем Земля

Заключение

Итого, мы изучили:

  • Контейнеры
  • Списки (создание, наполнение, функции для работы, индексы, слайсы)
  • Кортежи
  • Словари (ключ-значение, перезаписывание при наполнении)

Гигантский объём новой информации, да? Но ничего, ты делаешь офигенные успехи!

Если что – пиши, я помогу и постараюсь объяснить лучше.

Дальше мы рассмотрим основу логики в программировании – условия.


▲ В начало ▲

◀ Переменные и операции с ними Условия ▶