Списки
Список — мутабельна послідовність
Зазвичай списки використовуються для зберігання однотипних даних (хоча 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
.