+---------------------------+
|.-------------------------.|
|| kee_reel@blog:~/ru $ cd ||
|| ссылки контакты         ||
|| c c++ linux opengl sql  ||
|| python сети             ||
||                         ||
|.-------------------------.|
+-::---------------------::-+
.---------------------------.
 // /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 = [1, '2', 'Three', [3, 11.2]]

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

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

student_marks = []

Наполнение

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

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

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

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

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

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

В 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:

student_marks = [1, 3, 5]
print(student_marks[0]) # 1
print(student_marks[1]) # 3
print(student_marks[2]) # 5

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

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

Получаем значение по индексу с конца

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

my_list = [3, 5, 7]
print(student_marks[len(student_marks) - 1]) # 7
print(student_marks[len(student_marks) - 2]) # 5
print(student_marks[len(student_marks) - 3]) # 3

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

my_list = [3, 5, 7]
print(student_marks[-1]) # 7
print(student_marks[-2]) # 5
print(student_marks[-3]) # 3

Перезаписываем значение по индексу

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

student_mark[1] = 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)
print(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() умеет сортировать не только числа)
  • Вычисли во сколько раз Нептун дальше от Солнца, чем Земля

Заключение

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

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

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

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

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


▲ В начало ▲