Перейти до змісту

Списки

Список — мутабельна послідовність

Зазвичай списки використовуються для зберігання однотипних даних (хоча Python не забороняє зберігати в них дані різних типів).

Списки представлені класом list. Списки підтримуєть усі загальні для усіх та мутабельних послідовностей операції. Крім того списки реалізують один додатковий метод: sort().

Створення списків:

спосіб приклад
перераховування елементів в квадратних дужках [1,3,4,5]
порожній список []
спискові вирази (включення) [x ** 3 for x in range(10)]
використання конструктора класа list(range(8))

Конструктор класа може приймати будь-який ітерабельний об'єкт. З його елементів буде побудовано список.

Help on class list in module builtins:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable
's items
...

Спискові включення

Спискові включення (спискові вирази, list comprehension) дозволяють лаконічно описувати списки, які будуються по певним виразам, фільтровати їх і застосовувати функції до їх елементів. Синтаксис аналогичний синтаксису генераторів-виразів, але вирлаз заключається у квадратні дужки (хоча коректніше сказати, що синтаксис виразів-генераторів аналогічний синтаксису спискових включень, оскільки вони з'явились в Python значно пізніше спискових включень).

Приклад: отримати список квадратів цілих чисел від 0 до 10:

>>> [x**2 for x in range(11)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>>

Зауважте: спискове включення повертає об'єкти типу list:

>>> l = [int(x) for x in 'James Bond 007' if x.isdigit()]
>>> l
[0, 0, 7]
>>> type(l)
<class 'list'>
>>>

Дуже часто спискові вирази називають "генератори списків". Автор вважає таке формулювання некорректним.

Сортування списків

Списки можна сортувати за допомогою метода:

sort(*, key=None, reverse=None)

Метод сортує список модифікуючи його за допомогою операції "<" за зростанням.

  • Опціональний параметр key — це функція від одного аргумента, яка надає ключ для сортування.
  • reverse — якщо True, то сортування відбувається у зворотньому порядку.

Можна відсортувати список з будь-яких елементів які можна порівняти між собою.

Копіювання списків

Операція множення часто використовується зі списками для ініціалізації списка заданою кількістю однакових елементів:

>>> l = [0] * 10
>>> l
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>>

Операція '*' конкатенує неповні копії списків, тобто об'єкти всередині копій не копирюються, а зберігаються посилання на них. Завжди пам'ятайте про це, коли в списку знаходяться мутабельні об'єкти, наприклад, інші списки.

Початківці на Python часто припускаються подібної помилки, намагаючись ініціалізувати двовимірну матрицю за допомогою списків списків.

>>> def print_matrix(matrix):
...     """Функція вивода матриці"""
...     for row in matrix:
...         print(' '.join(str(element) for element in row))
...
>>> # Створення матриці 5x5 (неправильно)
>>> matrix_done_wrong = [[0] * 5] * 5
>>> print_matrix(matrix_done_wrong)
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>>> # поки що усе гаразд
>>> matrix_done_wrong[1][3] = 8
>>> # змінено один елемент
>>> print_matrix(matrix_done_wrong)
0 0 0 8 0
0 0 0 8 0
0 0 0 8 0
0 0 0 8 0
0 0 0 8 0
>>> # а змінились відповідні елементи в усіх рядках!

Відбулось таке через те, що список зберігає в себі посилання на об'єкти. Другий оператор * створив список з посилань на один і той самий список.

>>> matrix_done_wrong[0]
[0, 0, 0, 8, 0]
>>> matrix_done_wrong[4]
[0, 0, 0, 8, 0]
>>> matrix_done_wrong[0] is matrix_done_wrong[4]
True
>>>

Що ж робити?

Нам необхідно створювати кожен рядок матриці окремо, наприклад скориставшись методом append():

>>> matrix = []
>>> for _ in range(5):
...     matrix.append([0]*5)
...
>>> print_matrix(matrix)
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>>> matrix[1][3] = 8
>>> print_matrix(matrix)
0 0 0 0 0
0 0 0 8 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>>>

Але простіше і лаконічніше можна це зробити за допомогою спискового включення:

>>> matrix_done_right = [[0] * 5 for _ in range(5)]
>>> print_matrix(matrix_done_right)
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>>> matrix_done_right[1][3] = 8
>>> print_matrix(matrix_done_right)
0 0 0 0 0
0 0 0 8 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>>>

Для отримання глибоких копій об'єктів можна також скористатись функцією deepcopy модуля copy.

Back to top