10  Додаткові матеріали

Data Miorsh Ihor Miroshnychenko Youtube Monobank

10.1 Множини

Поміж різних типів даних у Python є ще один, який ми ще не мали нагоди використати, а саме множина. У математиці множина - це набір значень, в якому немає повторень. В Python множина (англ. set) - це структура даних, що містить унікальні елементи. Множини створюються за допомогою фігурних дужок {}.

Повернемося до прикладу houses.py, де ми створили список словників з даними про студентів Гоґвортсу:

students = [
        {'name': 'Гаррі Поттер', 'house': 'Ґрифіндор'},
        {'name': 'Герміона Грейнджер', 'house': 'Ґрифіндор'},
        {'name': 'Рон Уізлі', 'house': 'Ґрифіндор'},
        {'name': 'Драко Малфой', 'house': 'Слизерин'},
        {'name': 'Том Реддл', 'house': 'Слизерин'},
        {'name': 'Седрик Діггорі', 'house': 'Гафелпаф'},
        {'name': 'Луна Лавґуд', 'house': 'Рейвенклов'}
]

Припустимо, що наша мета — з’ясувати унікальні гуртожитки в Гоґвортсі у світі Гаррі Поттера?

Перший підхід, який приходить на думку, це створити список унікальних гуртожитків, переглянути всіх студентів та додати гуртожиток до списку, якщо його там ще немає:

unique_houses = []
for student in students:
    if student['house'] not in unique_houses:
        unique_houses.append(student['house'])

print(unique_houses)
['Ґрифіндор', 'Слизерин', 'Гафелпаф', 'Рейвенклов']

Другий підхід - використати множину за допомогою функції set(). Множина автоматично видаляє усі повторення, тому ми можемо просто створити множину з усіх гуртожитків:

unique_houses = set()
for student in students:
    unique_houses.add(student['house'])

print(unique_houses)
{'Слизерин', 'Рейвенклов', 'Гафелпаф', 'Ґрифіндор'}
Примітка

Документацію по різним типам даних Python можна знайти за посиланням https://docs.python.org/3/library/stdtypes.html.

10.1.1 Методи множин

Множини мають ряд методів, які дозволяють виконувати різні операції з множинами. Розглянемо декілька з них

  • add(element) - додає елемент до множини:
students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students.add('Драко Малфой')

print(students)
{'Герміона Грейнджер', 'Гаррі Поттер', 'Драко Малфой', 'Рон Уізлі'}
  • union(set) - повертає об’єднання двох множин:
students1 = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students2 = {'Драко Малфой', 'Том Реддл'}
all_students = students1.union(students2)

print(all_students)
{'Герміона Грейнджер', 'Гаррі Поттер', 'Драко Малфой', 'Рон Уізлі', 'Том Реддл'}
  • clear() - видаляє всі елементи множини:
students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students.clear()

print(students)
set()
  • copy() - повертає копію множини:
students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students2 = students.copy()

print(students2)
{'Герміона Грейнджер', 'Гаррі Поттер', 'Рон Уізлі'}
  • difference(set) - повертає різницю двох множин:
students1 = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students2 = {'Гаррі Поттер', 'Рон Уізлі'}
students3 = students1.difference(students2)

print(students3)
{'Герміона Грейнджер'}
  • discard(element) - видаляє елемент із множини, якщо він там є. Якщо елементу немає у множині, то нічого не відбувається:
students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students.discard('Гаррі Поттер')

print(students)
{'Герміона Грейнджер', 'Рон Уізлі'}
students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students.discard('Драко Малфой')

print(students)
{'Герміона Грейнджер', 'Гаррі Поттер', 'Рон Уізлі'}
  • remove(element) - видаляє елемент із множини, якщо він там є. Якщо елементу немає у множині, то видає помилку KeyError:
students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students.remove('Гаррі Поттер')

print(students)
{'Герміона Грейнджер', 'Рон Уізлі'}
students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students.remove('Драко Малфой')

print(students)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[12], line 2
      1 students = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
----> 2 students.remove('Драко Малфой')
      4 print(students)

KeyError: 'Драко Малфой'
  • intersection(set) - повертає перетин двох множин:
students1 = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students2 = {'Гаррі Поттер', 'Рон Уізлі'}
students3 = students1.intersection(students2)

print(students3)
{'Гаррі Поттер', 'Рон Уізлі'}
  • isdisjoint(set) - повертає True, якщо дві множини не мають спільних елементів. Наприклад:
students1 = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}
students2 = {'Драко Малфой', 'Том Реддл'}

print(students1.isdisjoint(students2))
True
  • issubset(set) - повертає True, якщо множина є підмножиною іншої множини. Наприклад:
students1 = {'Гаррі Поттер', 'Герміона Грейнджер'}
students2 = {'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'}

print(students1.issubset(students2))
True

10.1.2 Frozenset

У множини теж є незмінний аналог. Frozenset - це незмінний набір об’єктів, він має ту ж функціональність, що і set, але його елементи не можуть бути змінені після створення.

students = frozenset({'Гаррі Поттер', 'Герміона Грейнджер', 'Рон Уізлі'})
print(students)
frozenset({'Герміона Грейнджер', 'Гаррі Поттер', 'Рон Уізлі'})

На старті ви не так часто зіштовхуватиметеся з frozenset, але чим глибше ви занурюватиметеся в розробку, тим вище ймовірність, що ви зустрінетеся з frozenset при роботі з множинами.

Примітка

Документацію по frozenset Python можна знайти за посиланням https://docs.python.org/3/library/stdtypes.html#frozenset.

10.2 Глобальні змінні

У Python є можливість створювати змінні, які будуть доступні в усій програмі. Такі змінні називаються глобальними. Глобальні змінні можна створити за межами будь-якої функції, але вони будуть доступні в усій програмі. Для створення глобальної змінної потрібно використати ключове слово global.

Для прикладу створимо програму bank.py, яка буде відслідковувати баланс рахунку. Спочатку баланс рахунку буде дорівнювати 0:

balance = 0

def main():
    print("Баланс рахунку:", balance)

if __name__ == "__main__":
    main()
Баланс рахунку: 0

Навіть якщо ви оголосите змінну в Python поза межами ваших функцій ви можете отримати до неї доступ.

Тепер давайте додамо функції, які дозволить збільшувати та зменшувати баланс рахунку:

balance = 0

def increase_balance(amount):
    balance += amount

def decrease_balance(amount):
    balance -= amount

def main():
    increase_balance(100)
    decrease_balance(50)
    print("Баланс рахунку:", balance)

if __name__ == "__main__":
    main()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[18], line 15
     12     print("Баланс рахунку:", balance)
     14 if __name__ == "__main__":
---> 15     main()

Cell In[18], line 10, in main()
      9 def main():
---> 10     increase_balance(100)
     11     decrease_balance(50)
     12     print("Баланс рахунку:", balance)

Cell In[18], line 4, in increase_balance(amount)
      3 def increase_balance(amount):
----> 4     balance += amount

UnboundLocalError: cannot access local variable 'balance' where it is not associated with a value

При виконанні коду отримаємо помилку UnboundLocalError. Це трапляється через те, що Python не знає, що ми маємо на увазі, коли звертаємося до змінної balance всередині функції. Щоб виправити цю помилку, потрібно вказати, що ми маємо на увазі глобальну змінну balance:

balance = 0

def increase_balance(amount):
    global balance 
    balance += amount

def decrease_balance(amount):
    global balance 
    balance -= amount

def main():
    increase_balance(100)
    decrease_balance(30)
    print("Баланс рахунку:", balance)

if __name__ == "__main__":
    main()
Баланс рахунку: 70

Існує й інше рішення цієї задачі через об’єктно-орієнтоване програмування:

class BankAccount:
    def __init__(self):
        self._balance = 0

    @property
    def balance(self):
        return self._balance

    def increase_balance(self, amount):
        self._balance += amount

    def decrease_balance(self, amount):
        self._balance -= amount


def main():
    account = BankAccount()
    print("Баланс рахунку:", account.balance)
    account.increase_balance(100)
    account.decrease_balance(30)
    print("Баланс рахунку:", account.balance)

if __name__ == "__main__":
    main()
Баланс рахунку: 0
Баланс рахунку: 70

Використання глобальних змінних може призвести до певних проблем, особливо великих програмах. Тому використовуйте глобальні змінні обережно.

10.3 Константи

Деякі мови дозволяють визначати константи - значення, які неможливо змінити. Це дозволяє вам писати досить захищений код. На випадок, якщо хтось випадково спробує змінити значення цієї змінної, вона не може бути змінена, або, як правило, не може бути змінена без великих зусиль.

У Python немає спеціального синтаксису для визначення констант. Проте, константи можна визначити, використовуючи змінні з великими літерами. Це не забороняє змінювати значення цих змінних, але це є загальною практикою в багатьох мовах програмування:

PI = 3.14159
GRAVITY = 9.8

Аналогічно, ви можете використовувати константи в класах:

class Circle:
    PI = 3.14159

    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return Circle.PI * self.radius * self.radius

circle = Circle(5)
print(circle.area())
78.53975

10.4 Анотації типів

Python 3.5 вперше ввів підтримку анотацій типів. Це означає, що ви можете вказати типи аргументів та значень, які повертає функція. Це допомагає зрозуміти, які типи даних очікується від функції, а також допомагає знайти помилки в коді.

Створимо функцію meow(), яка приймає аргумент n типу int та повертає рядок:

def meow(n: int) -> str:
    return "meow " * n

print(meow(3))
meow meow meow 
Примітка

Документацію по анотаціям типів Python можна знайти за посиланням https://docs.python.org/3/library/typing.html.

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

Terminal
pip install mypy
Примітка

Документацію по mypy можна знайти за посиланням https://mypy.readthedocs.io/.

10.5 Docstrings

Docstrings - це рядок документації, який служить для пояснення роботи функції, класу чи модуля. Docstrings розміщуються в першому рядку функції, класу чи модуля, після рядка з імпортами. Docstrings можуть бути багаторядковими, тобто складатися з декількох рядків:

def meow(n: int) -> str:
    """
    Функція повертає рядок "meow" n разів.

    :param n: кількість разів
    :type n: int
    :return: рядок "meow" n разів
    :rtype: str
    """
    return "meow " * n
Примітка

Більше інформації про docstrings можна знайти за посиланням https://www.python.org/dev/peps/pep-0257/.

10.6 Розширені можливості командного рядка

Раніше ми розглянули, як використовувати командний рядок для передачі аргументів у програму за допомогою sys.argv. Давайте розглянемо деякі додаткові можливості.

Припустимо, що ми хочемо створити програму, яка приймає аргументи командного рядка у вигляді ключових слів. Наприклад, ми хочемо, щоб програма приймала аргументи -n, який вказує кількість разів, які потрібно вивести слово “meow”:

import sys

if len(sys.argv) == 1:
    print("meow")
elif len(sys.argv) == 3 and sys.argv[1] == "-n":
    n = int(sys.argv[2])
    print("meow " * n)
else:
    print("використання: python meow.py [-n <кількість>]")
використання: python meow.py [-n <кількість>]

Тепер ми можемо викликати програму з командного рядка:

Terminal
python meow.py -n 3

Якщо ж маштаби програми зростають, то можна використовувати бібліотеку argparse, яка дозволяє створювати більш складні програми з багатьма аргументами командного рядка:

import argparse

1parser = argparse.ArgumentParser(description="Функція повертає рядок 'meow' n разів.")
2parser.add_argument("-n", default=1, type=int, help="кількість разів")
3args = parser.parse_args()

print("meow " * args.n)
1
Ми створюємо об’єкт ArgumentParser з описом програми.
2
Додаємо аргумент командного рядка -n зі значенням за замовчуванням 1, типом int та описом.
3
Парсимо аргументи командного рядка.
Примітка

Більше інформації про argparse можна знайти за посиланням https://docs.python.org/3/library/argparse.html.

10.7 Розпакування

Розпакування - це процес розпакування послідовності елементів у змінні. Розпакування може бути корисним, коли ви хочете розпакувати значення зі списку, кортежу або словника. Розглянемо декілька прикладів.

- Розпакування списку

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

def total(galleons, sickles, knuts):
    return (galleons * 17 + sickles) * 29 + knuts

coins = [100, 50, 25]

1print(total(*coins), "Кнатів")
1
Ми використовуємо оператор * для розпакування списку coins у аргументи функції total.
50775 Кнатів

- Розпакування кортежу

Розпакування кортежу працює так само, як розпакування списку:

def total(galleons, sickles, knuts):
    return (galleons * 17 + sickles) * 29 + knuts

coins = (100, 50, 25)

print(total(*coins), "Кнатів")
50775 Кнатів

- Розпакування словника

Розпакування словника дозволяє передавати ключові слова як аргументи функції:

def total(galleons, sickles, knuts):
    return (galleons * 17 + sickles) * 29 + knuts

coins = {'galleons': 100, 'sickles': 50, 'knuts': 25}

1print(total(**coins), "Кнатів")
1
Ми використовуємо оператор ** для розпакування значень словника coins у аргументи функції total.
50775 Кнатів

10.8 Корисні функції

Також давайте подивимося на різні функції, які допомагають нам працювати зі списками та множинами:

  • len() - повертає кількість елементів у списку або множині. Наприклад:
fruits = ['apple', 'banana', 'orange']
print(len(fruits))
3
fruits = {'apple', 'banana', 'banana', 'apple'}
print(len(fruits))
2
  • max() - повертає найбільший елемент у списку або множині. Наприклад:
fruits = ['apple', 'banana', 'orange']
print(max(fruits))
orange
numbers = [5, 2, 8, 1, 9]
print(max(numbers))
9
my_set = {5, 2, 8, 1, 8}
print(max(my_set))
8
  • min() - повертає найменший елемент у списку або множині. Наприклад:
fruits = ['apple', 'banana', 'orange']
print(min(fruits))
apple
numbers = [5, 2, 8, 1, 9]
print(min(numbers))
1
  • sorted() - повертає відсортований список або множину. Вона може приймати параметр reverse=True, щоб відсортувати послідовність у зворотному порядку (за спаданням). Наприклад:
fruits = ['banana', 'orange', 'apple']
print(sorted(fruits))
['apple', 'banana', 'orange']
numbers = [5, 2, 8, 1, 9]
print(sorted(numbers, reverse=True))
[9, 8, 5, 2, 1]

А от якщо відсортувати множину, то вийде список!

my_set = {1, 1, 2, 2}
print(sorted(my_set))
[1, 2]

10.8.1 range()

Функція range() дозволяє створити послідовність чисел.

range(start, stop, step)
# start - з цього числа починаємо за замовчуванням 0
# stop - кінець послідовності, але саме число stop не включено до результату.
# step - крок переходу між числами за замовчуванням 1

Функція дозволяє нам генерувати послідовність цілих чисел із заданим початком, кінцем та кроком. Після виконання функція повертає спеціальний тип даних – range. Для зручнішої роботи з послідовністю можна перевести range до списку. Обов’язково потрібно вказати лише аргумент stop, початок та крок за умовчанням дорівнюють 0 і 1 відповідно. Розглянемо приклади:

# від 0 до 4 з кроком 1
list(range(5))
[0, 1, 2, 3, 4]
# від 2 до 9 з кроком 2
list(range(2, 10, 2))
[2, 4, 6, 8]
# від 10 до 2 з кроком 1
list(range(10, 1, -1))
[10, 9, 8, 7, 6, 5, 4, 3, 2]

Завдання 10.1
У змінну var_1 збережіть список з числами від -100 до 100 включно з кроком 1.

У змінну var_2 збережіть список з числами від 250 до 0 включно з кроком 2.

У змінну var_3 збережіть список з усіма непарними числами від 100 до 200.

Рішення
var_1 = list(range(-100, 101, 1))
var_2 = list(range(250, -1, -2))
var_3 = list(range(101, 200, 2))

Завдання 10.2
У змінних a та b зберігаються числа - початок і кінець діапазону. Напишіть програму, яка поверне суму всіх чисел із цього діапазону. Збережіть значення змінної result.

Приклад:

```{python}
a = 1
b = 3 

result = 6
```
Рішення
a = 1
b = 3
result = sum(range(a, b + 1))

10.9 Змінювані та незмінювані об’єкти

Настав час розібратися з досить складною для початківців концепцією змінних і незмінних об’єктів у Python. Ми вже знаємо, що можемо змінювати створені списки, наприклад, замінити або видалити один із елементів у списку. Однак ця особливість списку, його змінність призводить до несподіваних на перший погляд наслідків:

# збережемо список у змінну my_list_1
my_list_1 = [3, 1, 2]

# у змінну my_list_2 збережемо список my_list_1
my_list_2 = my_list_1

# змінимо список my_list_1
my_list_1.append(4)
my_list_1.sort()
my_list_1[0] = 100

# подивимося на обидва списки
print("Результат списку my_list_1:", my_list_1)
print("Результат списку my_list_2:", my_list_2)
Результат списку my_list_1: [100, 2, 3, 4]
Результат списку my_list_2: [100, 2, 3, 4]

Дивно, адже ми відсортували лише перший список, але другий також змінився! Вся справа в тому, що списки, масиви та словники — це об’єкти, що змінюються. Замість того, щоб створити ще одну коробочку в пам’яті з ім’ям my_list_2 та покласти в неї список із коробочки my_list_1, Python просто запам’ятав, що тепер на вихідну коробочку посилаються дві змінні. Коли змінюємо список my_list_1, змінюється і my_list_2. І навпаки, при зміні my_list_2 зміниться і my_list_1.

Саме тому список має метод copy(). Він дозволяє створити копію першого списку у новій змінній. У такому разі зміни першого списку вже не вплинуть на копію цього списку.

# збережемо список у змінну my_list_1
my_list_1 = [3, 1, 2]

# у змінну my_list_2 збережемо список my_list_1 з методом copy()
my_list_2 = my_list_1.copy()

# змінимо список my_list_1
my_list_1.append(4)
my_list_1.sort()
my_list_1[0] = 100

# подивимося на обидва списки
print("Результат списку my_list_1:", my_list_1)
print("Результат списку my_list_2:", my_list_2)
Результат списку my_list_1: [100, 2, 3, 4]
Результат списку my_list_2: [3, 1, 2]

Тому при роботі з об’єктами в Python важливо розуміти, чи змінюємо ми вихідний об’єкт чи створюємо новий. Уважно читайте документацію функцій та методів. Припустимо, ми маємо список my_list, ми хочемо завести новий список my_list_ordered з відсортованими елементами зі списку my_list:

my_list = [1, 2, 3, -2]

# так правильно
my_list_ordered = sorted(my_list) # функція sorted повертає новий список, не змінює список my_list
print("Результат списку my_list_ordered:", my_list_ordered)
print("Результат списку my_list:", my_list)
Результат списку my_list_ordered: [-2, 1, 2, 3]
Результат списку my_list: [1, 2, 3, -2]
# так неправильно
my_list_ordered = my_list.sort() # метод sort нічого не повертає, а лише змінює список my_list
print("Результат списку my_list_ordered:", my_list_ordered)
print("Результат списку my_list:", my_list)
Результат списку my_list_ordered: None
Результат списку my_list: [-2, 1, 2, 3]

А ось вже знайомі нам числа int і float, рядки та логічні значення - це незмінні об’єкти. Тобто після створення об’єкта не можна змінити його значення, лише створити новий об’єкт із зміненим значенням.

10.10 Кортежі

Незважаючи на деякі підводні камені, можливість змінювати списки та множини робить їх дуже зручними структурами для роботи. У процесі виконання програми ми можемо додавати, змінювати чи видаляти елементи.

Іноді можуть виникнути ситуації, коли хочемо зберігати набір елементів без можливості змінювати його. Тому у списків існує їхній незмінний аналог - кортежі (tuple). Кортежі створюються за допомогою круглих дужок (), а елементи розділені комами. Кортежі не можна змінювати після створення, тобто не можна додавати, видаляти чи змінювати елементи в кортежі. Тому кортежі краще використовувати, коли треба зберігати значення, які не змінюватимуться. Наприклад, назви місяців:

# створимо кортеж
months = ('January', 'February', 'March', 'April', 'May',
           'June', 'July', 'August', 'September', 'October', 'November', 'December')

# спробуємо додати тринадцятий місяць
months[12] = 'Undecimber'

# або змінити другий місяць
months[1] = 'Лютий'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[49], line 6
      2 months = ('January', 'February', 'March', 'April', 'May',
      3            'June', 'July', 'August', 'September', 'October', 'November', 'December')
      5 # спробуємо додати тринадцятий місяць
----> 6 months[12] = 'Undecimber'
      8 # або змінити другий місяць
      9 months[1] = 'Лютий'

TypeError: 'tuple' object does not support item assignment

При виконанні коду отримаємо помилку TypeError: 'tuple' object does no support item assignment. Помилка говорить про те, що кортеж не підтримує зміну чи додавання елементів, тому спроба привласнення нового значення елементу викликає помилку TypeError.

Кортежі в основному використовуються в тих місцях, де потрібна ефективність та продуктивність. Кортежі займають менше місця, ніж списки, та обробляються швидше. При цьому кортежі, як і списки, підтримують індексацію. Наприклад, якщо ми хочемо отримати назву першого місяця, можемо використовувати вже звичний запис:

month_index = 0
month_name = months[month_index] 
print(month_name)
January

Завдання 10.3
Створіть кортеж із назвами днів тижня та збережіть його у змінну days_of_the_week.

'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'
Рішення
days_of_the_week = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')

10.11 Функція zip() для об’єднання послідовностей

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

x = [1, 2, 3]
y = ['a', 'b', 'c']

# Використовуємо функцію zip() для об'єднання елементів із двох списків
result = zip(x, y)

# Перетворюємо результат на список
result_list = list(result)

print(result_list)
[(1, 'a'), (2, 'b'), (3, 'c')]

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

Зараз важливо запам’ятати, що за допомогою зв’язки list(zip(x, y)) ми можемо швидко й ефективно об’єднувати кілька списків.

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

10.12 Завдання

Завдання 10.4
Дано два списки list_1 і list_2. Відсортуйте list_1 за зростанням, а list_2 за спаданням. Поєднайте list_1 та list_2 в один відсортований за зростанням список list_3. У змінну list_3_len збережіть довжину list_3.

Приклад:

```{python}
list_1 = [1, 5, 3]
list_2 = [2, 8]
# -> 
list_1 = [1, 3, 5]
list_2 = [8, 2]
list_3 = [1, 2, 3, 5, 8]
list_3_len = 5
```
Рішення
list_1 = [1, 5, 3]
list_2 = [2, 8]

Завдання 10.5
У змінній menu зберігається множина усіх позицій меню кав’ярні, а в змінній stop - множина позицій меню кав’ярні, недоступних для замовлення сьогодні. Збережіть у змінну menu_today позиції меню, доступні для замовлення сьогодні.

Приклад:

```{python}
menu = {'White Chocolate Mocha', 'Americano', 'Flat White', 'Latte', 
        'Blueberry Muffin', 'Chocolate Chip Cookie'}
stop = {'White Chocolate Mocha', 'Blueberry Muffin'}

menu_today = {'Americano', 'Flat White', 'Latte', 'Chocolate Chip Cookie'}
```
Рішення
menu = {'White Chocolate Mocha', 'Americano', 'Flat White', 'Latte', 
        'Blueberry Muffin', 'Chocolate Chip Cookie'}
stop = {'White Chocolate Mocha', 'Blueberry Muffin'}

menu_today = menu - stop
# або
menu_today = menu.difference(stop)

Завдання 10.6
У змінній my_set множина (set) із чисел. У змінній to_delete число, яке потрібно видалити з my_set, якщо воно там є. Якщо такого числа немає в my_set нічого робити не треба.

Приклад:

```{python}
my_set = {0, 10, 100}
to_delete = 0
# ====>
my_set = {10, 100} # видалили 0

my_set = {0, 10, 100}
to_delete = -2
# ====>
my_set = {0, 10, 100} # нічого не робили

```
Рішення
my_set = {0, 10, 100}
to_delete = 0
my_set.discard(to_delete)

Завдання 10.7
У students зберігається множина студентів. Студент, ім’я якого записано в new_student, з іншого інституту, його ім’я потрібно додати в students. У змінній churn_student - студент, який хоче перевестися до іншого інституту, його ім’я потрібно прибрати зі students.

Приклад:

```{python}
students = {'Крупін Владислав', 'Крашеніннікова Олександра', "Михолап Мар'яна", 'Дробина Юлія', 'Алексєєва Віталіна'}
new_student = 'Піщікова Катерина'
churn_student = "Михолап Мар'яна"
# ->
students = {'Крупін Владислав', 'Крашеніннікова Олександра', 'Дробина Юлія', 'Алексєєва Віталіна', 'Піщікова Катерина'}
```
Рішення
students = {'Крупін Владислав', 'Крашеніннікова Олександра', 'Михолап Мар\'яна', 'Дробина Юлія', 'Алексєєва Віталіна'}
new_student = 'Піщікова Катерина'
churn_student = 'Михолап Мар\'яна'
students.add(new_student)
students.discard(churn_student)
# або
# students.remove(churn_student)

Завдання 10.8
У змінній da_students зберігаються імена студентів курсу “Аналітик даних”, а у змінній dv_students - імена студентів курсу “Візуалізація даних”. Збережіть у змінну students студентів, які навчаються на обох курсах.

Порядок елементів у students не має значення.

Приклад:

```{python}
# студенти курсу "Аналітик даних"
da_students = {'Крупін Владислав', 'Крашеніннікова Олександра', "Михолап Мар'яна", 'Дробина Юлія'}
# студенти курсу "Візуалізація даних"
dv_students = {"Михолап Мар'яна", 'Дробина Юлія', 'Алексєєва Віталіна'}

# результат
students = {"Михолап Мар'яна", 'Дробина Юлія'}
```
Рішення
da_students = {'Крупін Владислав', 'Крашеніннікова Олександра', "Михолап Мар'яна", 'Дробина Юлія'}
dv_students = {"Михолап Мар'яна", 'Дробина Юлія', 'Алексєєва Віталіна'}
students = da_students & dv_students
# або
students = da_students.intersection(dv_students)
# або
students = da_students - dv_students

Завдання 10.9
- У змінній numbers_list збережено список із цілими числами. У списку щонайменше два різних цілих числа. - У змінну numbers_list_ordered збережіть усі числа зі списку numbers_list, відсортовані за спаданням. При цьому список numbers_list не повинен змінюватися. - У змінну numbers_set збережіть множину унікальних чисел зі списку numbers_list. Доповніть цю множину наступним цілим числом після максимального числа з numbers_list. - У змінну numbers_frozenset збережіть незмінну множину з усіх унікальних чисел зі списку numbers_list, крім мінімального числа.

Приклад:

```{python}
# Приклад 1
numbers_list = [1, 5, 3, 3, 5]

numbers_list_ordered = [5, 5, 3, 3, 1]
numbers_set = set([1, 3, 5, 6])
numbers_frozenset = frozenset([3, 5])
```
```{python}
# Приклад 2
numbers_list = [-1, 0, 1]

numbers_list_ordered = [1, 0, -1]
numbers_set = set([-1, 0, 1, 2])
numbers_frozenset = frozenset([0, 1])
```
```{python}
# Приклад 3
numbers_list [-1, -5, -1]

numbers_list_ordered = [-1, -1, -5]
numbers_set = set([-5, -1, 0])
numbers_frozenset = frozenset([-1])
```
Рішення
numbers_list = [1, 1, 5, 3, 3, 5]
numbers_list_ordered = sorted(numbers_list, reverse=True)
numbers_set = set(numbers_list)
numbers_set.add(max(numbers_list) + 1)
numbers_frozenset = frozenset(sorted(set(numbers_list))[1:]) 

Data Miorsh Ihor Miroshnychenko Youtube Monobank