Теоретичні відомості#
Послідовності (списки, кортежі, множини) створюються на основі базових типів даних, вивчених раніше. Послідовність представляється у вигляді об’єктів, проіндексованих за допомогою їх позиції, висловленої цілим числом: перший, другий і далі до останнього.
Списки#
Списки — найбільш багатофункціональний тип даних, який записується як список елементів, розділених комами, і укладених в квадратні дужки. Список є одним з найбільш використовуваних типів даних в мові Python. Кожне окреме значення списку називається “елемент списку”. Елементи списку при зберіганні списку в пам’яті мають унікальні порядкові номери — “індекси” (нумерація безперервна і починається з 0).
Список дуже схожий на масив, який реалізований в процедурних мовах програмування. Різниця полягає в тому, що елементами списку можуть бути об’єкти різних типів. Розмір списку не статичний, його можна змінювати.
Список за своєю природою є змінним типом даних на відміну, наприклад, від рядків. Змінна, яка визначається як список, містить посилання на структуру в пам’яті, яка в свою чергу зберігає посилання на будь-які інші об’єкти або структури. При створенні списку в пам’яті резервується область, яку можна умовно назвати деяким “контейнером”, в якому зберігаються посилання на інші елементи даних в пам’яті. На відміну від таких типів даних, як число або рядок, вміст “контейнера” списку можна змінювати.
Створення, зміна, видалення списків і робота з його елементами. Базові операції#
Список можна створити за допомогою оператора []
або методу list
.
Список можна створити з нуля або більше елементів:
empty_list = []
weekdays = ['Monday', 'Tuesday','Wednesday']
weekdays
['Monday', 'Tuesday', 'Wednesday']
або
another_empty_list = list()
another_empty_list
[]
Створивши порожній список, можна заповнити його за допомогою методу append
, який додає елемент в кінець списку.
Крім того, мова Python надає можливість швидкого створення списків цілих значень, без необхідності їх перераховувати:
range(1, 5)
list(range(1, 5))
[1, 2, 3, 4]
В даному прикладі функція range
приймає два цілих аргумента і повертає список, який містить всі цілі числа в проміжку між заданими значеннями, включаючи перше і виключаючи друге.
Існує ще два способи виклику функції range
. Якщо їй передано тільки одне значення, то в результаті вона поверне список з цілими значеннями від 0 до N
, де N
— значення параметра:
range(10)
list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Якщо ж range
викликана з трьома аргументами, то останній з них інтерпретується як розмір кроку, тобто в результуючому списку значення йтимуть через проміжки, рівні кроку:
range(1, 10, 2)
list(range(1, 10, 2))
[1, 3, 5, 7, 9]
І ще один спосіб створити список — це генератори списків. Генератор списків — спосіб побудувати новий список, застосовуючи вираз до кожного елементу послідовності. Генератори списків дуже схожі на цикл for
. Загальний вигляд генератора наступний:
[вираз for змінна in послідовність]
,
де змінна
— ідентифікатор деякої змінної, послідовність
— послідовність значень, які приймає дана змінна (це може бути список, рядок або об’єкт, отриманий за допомогою функції range
), вираз
— деякий вираз, як правило, залежить від використаної в генераторі змінної, яким будуть заповнені елементи списку.
Приклади використання генераторів:
c = ['l', 'i', 's', 't']
print(c)
c = [c*3 for c in 'list']
print(c)
['l', 'i', 's', 't']
['lll', 'iii', 'sss', 'ttt']
Можлива і більш складна конструкція генератора списків:
c = [c * 3 for c in 'list' if c != 'i']
print(c)
c = [c + d for c in 'list' if c!='i' for d in 'spam' if d != 'a']
print(c)
['lll', 'sss', 'ttt']
['ls', 'lp', 'lm', 'ss', 'sp', 'sm', 'ts', 'tp', 'tm']
При створенні списку в змінній зберігається посилання на об’єкт, а не сам об’єкт. Це обов’язково слід враховувати при груповому присвоюванні. Групове присвоювання можна використовувати для чисел і рядків, але для списків цього робити не можна. При зміні однієї змінної в одному списку змінюватиметься змінна і в іншому списку, так як обидві змінні посилаються на один об’єкт.
Синтаксис звернення до елементів списку точно такий же, як і при зверненні до символів рядків — використовуємо оператор індексування ([]
).
numbers[0]
numbers[-1]
Індексом може бути будь-який вираз, що повертає ціле число, зокрема негативне. Якщо індекс менше нуля, то відлік індексу буде розпочато з кінця списку.
Список, який є елементом іншого списку, називають вкладеним і розглядається, як один елемент списку.
Довжина списку обчислюється за допомогою функції len
. Одне з застосувань цієї функції — визначення довжини списку в циклах, які здійснюють перебір елементів списку.
mylist = ['one','two','three','four','five']
i = 0
while i < len(mylist):
print(mylist[i])
i += 1
one
two
three
four
five
Приклад для вкладеного списку:
mylist = [[1, 'one'], [2, 'two'], [3, 'three'], 'four', 5]
print(len(mylist))
5
Обробка списків дозволяє застосовувати такі дії, як “слайсинг” або “зріз”. Для списку можна отримати зріз, об’єднати кілька списків і так далі:
a=['trees', 'grass', 123, 1234]
print(a[0])
print(a[3])
print(a[-2])
print(a[:2] + ['forest', 5 * 5])
print(3 * a[:3] + ['green'])
trees
1234
123
['trees', 'grass', 'forest', 25]
['trees', 'grass', 123, 'trees', 'grass', 123, 'trees', 'grass', 123, 'green']
Ще цікавий приклад, який здійснює доступ до потрібного елементу списку. Це нагадує непряму адресацію в процедурних мовах. Необхідно вивести на екран, наприклад, число 6.
mylist = [1, 2, [18, 45, 87, [7, 6]]]
print(mylist[2][3][1])
6
Нижче наведені додаткові операції, що дозволяють додавати, видаляти і замінювати елементи списку (x
— довільний об’єкт, s
і t
— послідовності однакового типу):
s[i] = x
− замінює елемент послідовності, на який вказує індекс i
на x
.
dels[i]
− видаляє елемент послідовності, на який вказує індекс i
.
s[i:j] = t
− замінює зріз послідовності від i
до j
на t
(видаляє з послідовності елементи, що входять до зрізу, і вставляє елементи з t
).
del s[i:j]
− видаляє з послідовності елементи, що входять до зрізу. Еквівалентно: s[i:j] = []
.
Ще до базових операцій належать операції конкатенації (додавання) і дублювання списку.
+
— операція конкатенації (додавання списків);
*
— операція дублювання списку n
раз.
Створення копії списку#
Раніше стверджувалося, що значення змінної зберігається в якомусь місці пам’яті комп’ютера і викликається в програму по імені цієї змінної. Це означає, що змінна “пов’язана” або “посилається” на відповідне місце в пам’яті. Точно так же зі значенням в пам’яті пов’язано і назву списку (і інших об’єктів Python).
Якщо спробувати отримати список b
шляхом привласнення йому значень всіх елементів списку а
:
a = [...]
b = a
то дві змінні a
і b
будуть пов’язані з одним і тим же списком, тому при зміні одного списку буде змінюватися і другий (адже це фактично один і той же список, до якого можна звертатися за двома різними іменами). Цю особливість Python потрібно враховувати при роботі зі списками.
Якщо в програмі потрібна саме копія списку (а не ще одне посилання на нього), можна використовувати зріз списку, який формує його повну копію:
b = a[:]
В результаті a
і b
будуть незалежними списками, і зміна одного з них не змінить другого.
Вбудовані функції для роботи зі списками#
max(list)
Функція max
повертає елементи зі списку list
з максимальним значенням.
У наступному прикладі показано використання функції max
.
list1, list2 = ['123', 'xyz', 'zara', 'abc'], [456, 700, 200]
print("Max value element : ", max(list1))
print("Max value element : ", max(list2))
Max value element : zara
Max value element : 700
min(list)
Функція min
повертає елементи зі списку list
з мінімальним значенням.
У наступному прикладі показано використання методу min
.
list1,list2 =['123', 'xyz', 'zara', 'abc'], [456, 700, 200]
print ("min value element: ", min(list1))
print ("min value element: ", min(list2))
min value element: 123
min value element: 200
Вбудовані методи для роботи зі списками#
lst.append(x)
Додавання елементу х
у кінець списку. Еквівалентно: s[len(s):] = [x]
Приклад:
lst = ['sss', 'fff', 'kkk', 1, 2]
lst.append(100)
print(lst)
['sss', 'fff', 'kkk', 1, 2, 100]
lst.extend(t)
Додавання кортежу або списку t
у кінець списку. Схоже на об’єднання списків, але створення нового списку не відбувається. Еквівалентно: s[len(s):] = t
Приклад:
lst1 = [1, 2, 3]
lst2 = ['one', 'two']
lst1.extend(lst2)
print(lst1)
[1, 2, 3, 'one', 'two']
lst.count(x)
Повертає число входжень елементу х
у список.
Приклад:
lst = ['sss', 'fff', 'kkk', 1, 2, 'sss', 'sss', 'ddd', 'sss']
print(lst.count('sss'))
4
lst.index(x)
Визначення першої зліва позиції елементу x
у списку lst
. Якщо такого елементу немає, з’являється повідомлення про помилку.
Приклад:
lst = ['fff', 'kkk', 'sss', 1, 2, 'sss', 'ddd', 'sss']
print(lst.index('sss'))
2
lst.insert(i, х)
Вставка у послідовність елементу х
перед i
-м елементом. Еквівалентно: s[i:i] = [x]
, якщо i ≥ 0
. Якщо значення індексу менше 0, то вставляється у початок списку, а якщо більше довжини послідовності, то — у кінець списку.
Приклад:
aList = [123, 'xyz', 'zara', 'abc']
aList.insert(3, 2017)
print("Final List: ", aList)
Final List: [123, 'xyz', 'zara', 2017, 'abc']
lst.pop( [i])
Повертає i
-й елемент послідовності, одночасно видаляючи його зі списку. Якщо індекс не вказано, мається на увазі останній елемент списку. Положення елементу можна відраховувати з кінця, вказуючи негативний індекс. Якщо індекс виходить за межі діапазону, генерується виключення IndexError
.
Приклад:
aList = [123, 'xyz', 'zara', 'abc']
print("A List: ", aList.pop())
print("B List: ", aList.pop(2))
print(aList)
A List: abc
B List: zara
[123, 'xyz']
lst.remove(x)
Видаляє зі списку перший елемент зі значенням х
. Еквівалентно: del lst[lst.index(x)]
. Якщо такого у списку немає, то генерується виключення ValueError
.
Приклад:
aList = [123, 'xyz', 'zara', 'abc', 'xyz']
aList.remove('xyz')
print("List: ", aList)
aList.remove('abc')
print("List: ", aList)
List: [123, 'zara', 'abc', 'xyz']
List: [123, 'zara', 'xyz']
lst.reverse()
Розташовує елементи послідовності у зворотному порядку. Новий список не створюється.
Приклад:
aList = [123, 'xyz', 'zara', 'abc', 'xyz']
aList.reverse()
print("List: ", aList)
List: ['xyz', 'abc', 'zara', 'xyz', 123]
lst.sort()
Розташовує елементи послідовності у порядку зростання. Новий список не створюється.
Приклад:
aList = ['123', 'xyz', 'zara', 'abc', 'xyz']
aList.sort()
print("List: ", aList)
List: ['123', 'abc', 'xyz', 'xyz', 'zara']
lst.clear()
Очищує список.
Функції вищого порядку для обробки послідовностей#
Функцію, яка приймає іншу функцію як аргумент або повертає іншу функцію, називають функцією вищого порядку або “first-class-function”.
Функції mар
, zip
, filter
, reduce
, lambda
дозволяють досить просто виконувати різні маніпуляції з даними, для чого у “звичайному” процедурному стилі доводиться писати трохи більше коду. Все нижче написане відноситься до так званого функціонального програмування.
map
#
Вбудована функція map
дозволяє застосувати функцію до кожного елементу послідовності. Функція має наступний формат:
mар(<функція>, <послідовність 1> [..., <послідовність n>])
Функція map
повертає об’єкт, що підтримує ітерації. Щоб отримати список, необхідно результат передати в функцію list
. Як параметр <функція>
вказується посилання на функцію (назва функції без круглих дужок), якій буде передаватися поточний елемент послідовності. Усередині функції зворотного виклику необхідно повернути нове значення.
Приклад:
# Додати до кожного елементу списку число 10
def func(elem):
return elem + 10
arr = [1, 2, 3, 4, 5]
print(list(map(func, arr)))
[11, 12, 13, 14, 15]
Функції map
можна передати кілька послідовностей. В цьому випадку в функцію зворотного виклику будуть передаватися відразу кілька елементів, розташованих в послідовності на однаковому зміщенні.
Приклад:
# Підсумувати елементи 3-х різних списків
def func(el, е2, еЗ):
return el + е2 + еЗ # повертає нове значення
arrl = [1, 2, 3, 4, 5]
arr2 = [10, 20, 30, 40, 50]
arr3 = [100, 200, 300, 400, 500]
print(list(map(func,arrl,arr2,arr3)))
[111, 222, 333, 444, 555]
Якщо кількість елементів в послідовності буде різною, то вибирається послідовність з мінімальною кількістю елементів.
zip
#
Функція zip
на кожній ітерації повертає кортеж, що містить елементи послідовностей, які розташовані на однаковому зміщенні. Щоб отримати список, необхідно результат передати в функцію list
.
Приклад 1:
a = [1, 2]
b = [3, 4]
c = [5, 6]
print(list(zip(a, b, c)))
[(1, 3, 5), (2, 4, 6)]
В якості ще одного прикладу переробимо програму підсумовування елементів трьох списків і використаємо функцію zip
замість функції map
.
Приклад 2:
arr1 = [1, 2, 3, 4, 5]
arr2 = [10, 20, 30, 40, 50]
arr3 = [100, 200, 300, 400, 500]
arr = [x + y + z for (x, y, z) in zip(arr1, arr2, arr3)]
print(arr)
[111, 222, 333, 444, 555]
filter
#
Функція filter
дозволяє фільтрувати значення послідовності. В результуючому списку тільки ті значення, для яких значення функції для елемента істинно. Формат функції:
filter(<функція>, <послідовність>)
Приклад:
# видалити всі від'ємні значення зі списку
def func(x):
return x >= 0
arr = [-1, 2, -3, 4, 0, -20, 10]
arr = list(filter(func, arr))
print(arr)
[2, 4, 0, 10]
# використання генераторів списків
arr = [-1, 2, -3, 4, 0, -20, 10]
arr = [i for i in arr if func(i)]
print(arr)
[2, 4, 0, 10]
reduce
#
Функція reduce
із модуля functools
бере два перших елемента, застосовує до них функцію, бере значення і третій елемент, і таким чином згортає об’єкт, який підтримує ітерації, до єдиного значення. Формат функції:
reduce(<функція>, <послідовність> [,<початкове значення>])
Приклад:
from functools import reduce
func = lambda el_prev, el: el_prev + el
reduce(func, [1, 2, 3, 4])
10
Але рекомендується використовувати звичайний прохід по елементам за допомогою for
для підвищення читання коду.
Кортежі#
Кортеж — це незмінний список. Кортеж не може бути змінений ніяким способом після його створення. Іншими словами, можна отримати елемент за індексом, але змінити його не можна.
Приклади:
a_tuple = ("a", "b", "z", "example") # створюємо кортеж
print(a_tuple)
print(a_tuple[0]) # отримуємо елемент за індексом
print(a_tuple[-1]) # отримати останній елемент 'example'
print(a_tuple[1:3]) # отримуємо зріз
('a', 'b', 'z', 'example')
a
example
('b', 'z')
Спільності і відмінності між кортежами і списками#
Кортеж визначається так само, як список, за винятком того, що набір елементів укладається в круглі дужки, а не в квадратні.
Елементи кортежу задані в певному порядку, як і в списку. Елементи кортежу індексуються з нуля, як і елементи списку, таким чином, перший елемент не порожнього кортежу — це завжди
a_tuple[0]
.Від’ємні значення індексу відраховуються від кінця кортежу, як і в списку. Останній елемент має індекс -1.
Створення зрізу кортежу (“slicing”) аналогічно створенню зрізу списку. Коли створюється зріз списку, виходить новий список; коли створюється зріз кортежу, виходить новий кортеж.
Основна відмінність між кортежами і списками полягає в тому, що кортежі не можуть бути змінені. На практиці це означає, що у них немає методів, які б дозволили їх змінити. У списків є такі методи, як
append
,extend
,insert
,remove
,pop
. У кортежів жодного із цих методів немає.
Основні операції з кортежами#
len(t)
Визначає кількість елементів кортежу (результатом є число, довжина t
).
t1 + t2
Об’єднання кортежів. Виходить новий кортеж, в якому після елементів кортежу t1
знаходяться елементи кортежу t2
.
t * n
чиn * t
n
-кратне повторення кортежу.
min(t)
Визначається елемент з найменшим значенням відповідно до алфавітного (“словникового”) порядку.
max(t)
Визначається елемент з найбільшим значенням відповідно до алфавітного (“словникового”) порядку.
Важливо розуміти, що “словниковий” порядок — спочатку числа по зростанню, потім рядки, що починаються на цифри в порядку їх зростання, потім рядки, що починаються на великі літери в алфавітному порядку, а потім рядки, що починаються на малі літери також в алфавітному порядку, − завжди використовується в обчислювальній техніці при сортуванні імен об’єктів.
Так де ж можуть стати в нагоді кортежі?
Кортежі в деяких випадках швидші, ніж списки. Але такі оптимізації в кожному конкретному випадку вимагають додаткових досліджень.
Кортежі роблять код безпечніше в тому випадку, якщо у вас є “захищені від запису” дані, які не повинні змінюватися.
Деякі кортежі можуть використовуватися в якості елементів множини і ключів словника (конкретно, кортежі, що містять незмінні значення, наприклад, рядки, числа та інші кортежі). Списки ніколи не можуть використовуватися в якості ключів словника, тому що списки — змінювані об’єкти.
Кортежі можуть бути перетворені в списки і навпаки. Вбудована функція tuple
приймає список і повертає кортеж із усіх його елементів, функція list
приймає кортеж і повертає список. По суті справи, tuple
заморожує список, а list
розморожує кортеж.
Приклад:
s = 'spring'
t = tuple(s)
print(t)
('s', 'p', 'r', 'i', 'n', 'g')
Множини#
Множина в мові Python — це структура даних, еквівалентна множинам в математиці. Множина може складатися з різних елементів. Цей тип даних є неврегульованим, як наслідок неіндексованим, змінним і ітеративним. Також множина не зберігає в собі два однакових елемента:
set([1, 1, 1, 2, 2, 2, 3, 3, 3, 4])
{1, 2, 3, 4}
У множину можна додавати і видаляти елементи, можна перебирати елементи множини, можна виконувати операції над множинами (об’єднання, перетин, різниця). Можна перевіряти приналежність елементу множини.
У множину можна перетворювати списки, кортежі і рядки, а множини, в свою чергу, можна перетворювати в списки і кортежі. Оскільки множини − ітеріративні, їх можна передавати безпосередньо в цикл for:
a = set([1, 2, 3])
for i in a:
print(i)
1
2
3
Елементами множини може бути будь-який незмінний тип даних: числа, рядки, кортежі. Змінні типи даних не можуть бути елементами множини, зокрема, не можна зробити елементом множини список (але можна зробити кортеж) або іншу множину. Вимога незмінності елементів множини визначена особливостями подання множини в пам’яті комп’ютера.
Множина задається перерахуванням всіх його елементів в фігурних дужках. Наприклад: A = {1, 2, 3}
Винятком є порожня множина, яку можна створити за допомогою функції set
. Якщо функції set
передати в якості параметра список, рядок або кортеж, то вона поверне множина, складену із елементів списку, рядки, кортежу. наприклад:
A = set('qwerty')
print(A)
{'w', 'r', 'q', 'e', 't', 'y'}
Кожен елемент може входити у множину тільки один раз, порядок проходження елементів не важливий. Наприклад, програма:
A = {1, 2, 3}
B = {3, 2, 1}
print(A == B)
True
виведе True
, так як A
і B
— рівні множини.
Кожен елемент може входити в множину тільки один раз. set('Hello')
поверне множину із чотирьох елементів: {'H','e','l','o'}
.
Робота з елементами множин#
Дізнатися число елементів у множині можна за допомогою функції len
.
Перебрати всі елементи множини (в невизначеному порядку!) можна за допомогою циклу for
:
c = {1, 2, 3, 4, 5}
for elem in c:
print(elem)
1
2
3
4
5
Перевірити, чи належить елемент множини, можна за допомогою операції in
, що повертає значення типу bool
:
i in A
Аналогічно є протилежна операція not in
.
Щоб додати елемент в множину є метод add
:
A.add(x)
Для видалення елемента x
із множини є два методи: discard
і remove
. Їх поведінка відрізняється лише в разі, коли видаляється елемент відсутній у множині. У цьому випадку метод discard
не робить нічого, а метод remove
генерує виняток KeyError
.
Нарешті, метод pop
видаляє із множини один випадковий елемент і повертає його значення. Якщо ж множина порожня, то генерується виключення KeyError
.
З множини можна зробити список за допомогою функції list
.
Операції з множинами#
З множинами в Python можна виконувати звичайні для математики операції над множинами.
|
Повертає множину, що є об’єднанням множин |
|
Додає у множину |
|
Повертає множину, що є перетином множин |
|
Залишає у множині |
|
Повертає різницю множин |
|
Видаляє із множини |
|
Повертає симметрическую різницю множин |
|
Записує до |
|
Повертає |
|
Повертає |
|
Еквивалентно |
|
Еквивалентно |