Теоретичні відомості#

Послідовності (списки, кортежі, множини) створюються на основі базових типів даних, вивчених раніше. Послідовність представляється у вигляді об’єктів, проіндексованих за допомогою їх позиції, висловленої цілим числом: перший, другий і далі до останнього.

Списки#

Списки — найбільш багатофункціональний тип даних, який записується як список елементів, розділених комами, і укладених в квадратні дужки. Список є одним з найбільш використовуваних типів даних в мові 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

Вбудовані методи для роботи зі списками#

  1. lst.append(x)

Додавання елементу х у кінець списку. Еквівалентно: s[len(s):] = [x]

Приклад:

lst = ['sss', 'fff', 'kkk', 1, 2]
lst.append(100)
print(lst)
['sss', 'fff', 'kkk', 1, 2, 100]
  1. 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']
  1. lst.count(x)

Повертає число входжень елементу х у список.

Приклад:

lst = ['sss', 'fff', 'kkk', 1, 2, 'sss', 'sss', 'ddd', 'sss']
print(lst.count('sss'))
4
  1. lst.index(x)

Визначення першої зліва позиції елементу x у списку lst. Якщо такого елементу немає, з’являється повідомлення про помилку.

Приклад:

lst = ['fff', 'kkk', 'sss', 1, 2, 'sss', 'ddd', 'sss']
print(lst.index('sss'))
2
  1. 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']
  1. 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']
  1. 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']
  1. lst.reverse()

Розташовує елементи послідовності у зворотному порядку. Новий список не створюється.

Приклад:

aList = [123, 'xyz', 'zara', 'abc', 'xyz']
aList.reverse()
print("List: ", aList)
List:  ['xyz', 'abc', 'zara', 'xyz', 123]
  1. lst.sort()

Розташовує елементи послідовності у порядку зростання. Новий список не створюється.

Приклад:

aList = ['123', 'xyz', 'zara', 'abc', 'xyz']
aList.sort()
print("List: ", aList)
List:  ['123', 'abc', 'xyz', 'xyz', 'zara']
  1. 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')

Спільності і відмінності між кортежами і списками#

  1. Кортеж визначається так само, як список, за винятком того, що набір елементів укладається в круглі дужки, а не в квадратні.

  2. Елементи кортежу задані в певному порядку, як і в списку. Елементи кортежу індексуються з нуля, як і елементи списку, таким чином, перший елемент не порожнього кортежу — це завжди a_tuple[0].

  3. Від’ємні значення індексу відраховуються від кінця кортежу, як і в списку. Останній елемент має індекс -1.

  4. Створення зрізу кортежу (“slicing”) аналогічно створенню зрізу списку. Коли створюється зріз списку, виходить новий список; коли створюється зріз кортежу, виходить новий кортеж.

  5. Основна відмінність між кортежами і списками полягає в тому, що кортежі не можуть бути змінені. На практиці це означає, що у них немає методів, які б дозволили їх змінити. У списків є такі методи, як append, extend, insert, remove, pop. У кортежів жодного із цих методів немає.

Основні операції з кортежами#

  1. len(t)

Визначає кількість елементів кортежу (результатом є число, довжина t).

  1. t1 + t2

Об’єднання кортежів. Виходить новий кортеж, в якому після елементів кортежу t1 знаходяться елементи кортежу t2.

  1. t * n чи n * t

n-кратне повторення кортежу.

  1. min(t)

Визначається елемент з найменшим значенням відповідно до алфавітного (“словникового”) порядку.

  1. max(t)

Визначається елемент з найбільшим значенням відповідно до алфавітного (“словникового”) порядку.

Важливо розуміти, що “словниковий” порядок — спочатку числа по зростанню, потім рядки, що починаються на цифри в порядку їх зростання, потім рядки, що починаються на великі літери в алфавітному порядку, а потім рядки, що починаються на малі літери також в алфавітному порядку, − завжди використовується в обчислювальній техніці при сортуванні імен об’єктів.

Так де ж можуть стати в нагоді кортежі?

  1. Кортежі в деяких випадках швидші, ніж списки. Але такі оптимізації в кожному конкретному випадку вимагають додаткових досліджень.

  2. Кортежі роблять код безпечніше в тому випадку, якщо у вас є “захищені від запису” дані, які не повинні змінюватися.

  3. Деякі кортежі можуть використовуватися в якості елементів множини і ключів словника (конкретно, кортежі, що містять незмінні значення, наприклад, рядки, числа та інші кортежі). Списки ніколи не можуть використовуватися в якості ключів словника, тому що списки — змінювані об’єкти.

Кортежі можуть бути перетворені в списки і навпаки. Вбудована функція 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 можна виконувати звичайні для математики операції над множинами.

A | B
A.union(B)

Повертає множину, що є об’єднанням множин A і B.

A |= B
A.update(B)

Додає у множину A все елементи із множини B.

A & B
A.intersection(B)

Повертає множину, що є перетином множин A і B.

A &= B
A.intersection_update(B)

Залишає у множині A тількі ті елементи, які є у множині B.

A - B
A.difference(B)

Повертає різницю множин A і B (елементи, що входять до A, але не входять до B).

A -= B
A.difference_update(B)

Видаляє із множини A все елементи, що входять до B.

A ^ B
A.symmetric_difference(B)

Повертає симметрическую різницю множин A і B

A ^= B
A.symmetric_difference_update(B)

Записує до A симетричну різницю множин A і B.

A <= B
A.issubset(B)

Повертає true, якщо A − підмножина B.

A >= B
A.issuperset(B)

Повертає true, якщо B − підмножина A.

A < B

Еквивалентно A <= B and A != B

A > B

Еквивалентно A >= B and A != B