You are on page 1of 145

Центральноукраїнський державний педагогічний університет

імені Володимира Винниченка

Рєзіна О.В., Дроговоз Н.А.

Програмув
ання
Навчально-методичний посібник
мовою
Python.
Об’єктний
підхід

Кропивницький – 2021
Рекомендовано до друку методичною радою Центральноукраїнського
державного педагогічного університету імені Володимира Винниченка
(протокол № від )

Рецензенти:
Авраменко О.В. – доктор фізико-математичних наук, професор кафедри
прикладної математики, економіки та статистики ЦДПУ імені В. Винниченка
Паращук С.Д. – кандидат фізико-математичних наук, доцент кафедри
інформатики та інформаційних технологій ЦДПУ імені В. Винниченка

Рєзіна О.В., Дроговоз Н.А. Програмування мовою Python. Структурний


підхід. Навчально-методичний посібник. – Кропивницький: РВВ ЦДПУ імені
Володимира Винниченка, 2021. – 144 с.

У посібнику розглянуті основні питання об’єктно-орієнтованого


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

© Рєзіна О.В., Дроговоз Н.А., 2021


ЗМІСТ

Передмова.......................................................................................................
Розділ І. Об'єктно-орієнтоване програмування...........................................
Тема №1. Поняття об'єктно-орієнтованого програмування. Створення
класів і об’єктів............................................................................................................
Тема №2. Методи.......................................................................................................12
Тема №3. Наслідування.............................................................................................17
Тема № 4. Поліморфізм.............................................................................................23
Тема № 5 Перезавантаження операторів, методів та функцій..............................35
Тема № 6. Абстракція та інкапсуляція.....................................................................47
Розділ ІІ. Графічний інтерфейс користувача.............................................65
Тема №7. Віджети мітка, кнопка, текстове поле....................................................65
Тема №8. Віджети перемикачі та прапорці.............................................................88
Тема №9. Віджети список, прокрутка та поле зі списком...................................102
Розділ ІІІ. Візуалізація даних....................................................................114
Тема №10. Бібліотека Matplotlib. Графіки функцій..............................................114
Тема №11. Моделювання засобами комп’ютерної графіки.................................134
Рекомендовані джерела.............................................................................144

3
Передмова
Пропонований посібник є логічним продовженням роботи
«Програмування мовою Python. Структурний підхід». Об’єктно-орієнтоване
програмування (ООП) дає можливість розв’язати задачу структурного
програмування на новому рівні, який передбачає структурування даних
методом моделювання інформаційних об’єктів. Такий підхід дає можливість
покращити процес управління програмним кодом, що є важливим при
реалізації крупних проектів.
Об’єктно-орієнтоване програмування є широко відомим підходом до
розробки комп’ютерних програм, який надає потужні засоби структурування,
повторного використання та захисту коду. Парадигма ООП спирається на
концепцію класів та об’єктів, її використовують у більшості навчальних
програм підготовки програмістів. Існує багато об’єктно-орієнтованих мов
програмування, включно із JavaScript, C ++, Java та Python.
Програмні коди, що досліджувалися в посібнику «Програмування мовою
Python. Структурний підхід», у дійсності базувалися на використанні об’єктів.
Об’єкти використовувалися в операторах, функціях, для них викликалися
методи. Але використання об’єктів було неявним. У запропонованому
посібнику розглядається створення класів та об’єктів, які в подальшому
використовуються в ієрархії наслідування. У першому розділі висвітлені
основні поняття і концепції ООП: класи, об’єкти, наслідування, поліморфізм,
перезавантаження операторів, абстракція та інкапсуляція.
У другому розділі розглядаються особливості розробки графічного
інтерфейсу користувача з точки зору об’єктного підходу. Тобто віджети
графічного модуля досліджуються як об’єкти відповідних класів.
У третьому розділі представлені можливості побудови графіків функцій та
діаграм різних типів засобами модуля matplotlib. Матеріал цього модуля може
бути використаний для самостійної роботи студентів.
До структури кожної теми входить теоретичний матеріал, практичні
індивідуальні завдання та питання для самоконтролю у тому числі з аналізом
програмного коду. Виклад теоретичних відомостей супроводжується
достатньою кількістю прикладів.
Посібник може бути корисним як студентам фізико-математичного
факультету педагогічного університету, так і всім, хто цікавиться об’єктно-
орієнтованим програмуванням та проблемами кодування комп’ютерної
графіки.

4
Розділ І. Об'єктно-орієнтоване програмування
Тема №1. Поняття об'єктно-орієнтованого програмування.
Створення класів і об’єктів
Мета: формування вмінь створення класів і об’єктів, визначення властивостей
об’єктів та атрибутів класу.
Теоретичні питання
План
1. Поняття об'єктно-орієнтованого програмування.
2. Поняття класу та об’єкта.
3. Визначення класу в Python.
4. Створення об’єктів

1. Поняття об'єктно-орієнтованого програмування

Об'єктно-орієнтоване програмування (OOP) – це парадигма


програмування, яка забезпечує засоби структурування програм таким чином,
що властивості та поведінка об'єднуються в окремі об'єкти.
Наприклад, об'єкт може представляти людину із властивостями: ім’я, вік,
адреса тощо, з такою поведінкою, як ходьба, розмова, дихання та біг. Або
електронний лист із властивостями, такими як список одержувачів, тематика,
тіло тощо, та поведінка, як додавання вкладених файлів та надсилання.
Інакше кажучи, об’єктно-орієнтоване програмування – це підхід для
моделювання конкретних реальних речей, таких як машини, а також відносини
між такими, як компанії та працівники, студенти та викладачі тощо. OOP
моделює суб'єкти реального світу як об'єкти програмного забезпечення, які
деякі дані, пов'язані з ними, і можуть виконувати певні функції.
Інша поширена парадигма програмування – це процедурне
програмування, яке структурує програму як рецепт, оскільки вона містить
набір кроків у вигляді функцій та блоків коду, які послідовно протікають для
виконання завдання.
Ключовий висновок полягає в тому, що об’єкти знаходяться в центрі
об'єктно-орієнтованої парадигми програмування, не тільки представляючи дані,
як у процедурному програмуванні, але й у загальній структурі програми.

2. Поняття класу та об’єкта


Кожний об’єкт є екземпляром деякого класу.
Прості структури даних, доступні в Python, як числа, рядки та списки,
призначені для відображення простих речей, таких як вартість чогось, назва
вірша, колір тощо. Що робити, якщо ви хотіли представляти щось набагато
складніше? Наприклад, ви хотіли би відслідковувати декілька різних тварин.
5
Якщо б ви використовували список, першим елементом могло бути ім’я
тварини, а другим його вік.
Але
Як знати, де який елемент? Що робити, якщо у вас було 100 різних тварин?
Ви впевнені, що кожна тварина має і ім’я, і вік, і так далі? Що робити, якщо ви
хотіли додати цим властивостям інші властивості? У такому підході не
вистачає організації, яку надають класи.
Класи використовуються для створення нових визначених користувачем
структур даних, які містять довільну інформацію про щось. У випадку з
твариною ми могли б створити клас Animal() для відстеження властивостей
щодо Тварини, таких як ім’я та вік.
Важливо зауважити, що клас просто забезпечує структуру – це окреслення
того, як щось слід визначити, але він фактично не забезпечує реального вмісту
сам по собі. Клас Animal() може вказати, що ім'я та вік необхідні для
визначення тварини, але він фактично не визначає, яке ім'я або вік конкретної
тварини.
Необхідно розглядати клас як ідею того, як щось слід визначити.
Об'єкти Python (екземпляри)
Клас є описом, а екземпляр – це реалізація класу з фактичними
значеннями, об'єкт, що належить певному класу. Це вже не ідея; це фактична
тварина, як собака на ім'я Роджер, якому вісім років.
По-іншому, клас схожий на форму чи анкету. Він визначає необхідну
інформацію. Після заповнення форми ваша конкретна копія є екземпляром
класу; вона містить актуальну для вас інформацію.
Ви можете заповнити кілька примірників, але без форми ви не знали б, яка
інформація потрібна. Таким чином, перш ніж ви зможете створити окремі
екземпляри об'єкта, ми повинні спочатку вказати, що потрібно, визначивши
клас (рис.1.1).

Рис. 1.1. Визначення класу

Клас – опис, створений програмістом для об'єкта. Клас визначає набір


атрибутів, які характеризуватимуть будь-який об'єкт, який створюється з цього
класу.
6
Об'єкт – екземпляр класу. Це реалізована версія класу, у якій клас
проявляється в програмі.

3. Визначення класу в Python:

class Dog:
pass

Визначення починається з ключового слова class, щоб вказати, що ви


створюєте клас, потім додаєте ім'я класу (з використанням підходу CamelCase
до імен класів, починаючи з великої літери.)
Створення екземплярів
a = Dog()
print(a)
b = Dog()
print(b)
print(a==b)
print(type(a))

Атрибути екземпляра

Усі класи створюють об'єкти, а всі об'єкти


містять характеристики (рис. 1.2), так звані
атрибути (властивості). Необхідно використати
метод __init __ (), щоб ініціалізувати (вказати)
початкові атрибути об'єкта, надавши їм своє
значення за замовчуванням (або стан). Цей метод
повинен мати принаймні один аргумент, а також
змінну self, що стосується самого об'єкта
(наприклад, Dog).
Рис. 1.2. Клас Dog
class Dog:

# Initializer / Instance Attributes


def __init__(self, name, age):
self.name = name
self.age = age

Кожний собака має конкретне ім’я та вік, що, очевидно, важливо знати,
коли ви починаєте фактично створювати різних собак (рис. 1.3). Пам’ятайте:
клас призначений саме для визначення Собаки, а не фактичного створення
примірників окремих собак із конкретними назвами та віком. Не всі собаки

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

Рис. 1. 2. Екземпляри класу


Атрибути приєднуються до екземплярів за допомогою присвоювання
значень спеціальному аргументу з іменем self.

Атрибути класу
Атрибути екземплярів специфічні для кожного об'єкта, а атрибути класу
однакові для всіх об’єктів – у цьому випадку для всіх собак.

class Dog:

# Class Attribute
species = 'mammal'

# Initializer / Instance Attributes


def __init__(self, name, age):
self.name = name
self.age = age

Отже, хоча кожний собака має унікальне ім’я та вік, кожний собака буде
ссавцем.

8
4. Створення об’єктів
class Dog:

# Class Attribute
species = 'mammal'

# Initializer / Instance Attributes


def __init__(self, name, age):
self.name = name
self.age = age

# Instantiate the Dog object


philo = Dog("Philo", 5)
mikey = Dog("Mikey", 6)

# Access the instance attributes


print("{} is {} and {} is {}.".format(
philo.name, philo.age, mikey.name, mikey.age))

# Is Philo a mammal?
if philo.species == "mammal":
print("{0} is a {1}!".format(philo.name,
philo.species))

Ми створили новий екземпляр класу Dog () і пов’язали його із змінною


philo. Потім ми передали йому два аргументи, " Philo" та 5. Ці атрибути
передаються методу __init__, який викликається кожного разу, коли ви
створюєте новий екземпляр, приєднуючи ім'я та вік до об'єкта. Нам не потрібно
передавати аргументи в параметр self.
Функція, яка створює новий екземпляр класу називається конструктором.
Це магія Пітона; коли ви створюєте новий екземпляр класу, Python
автоматично визначає, що таке self (собака в даному випадку) і передає його
методу __init__.
Приклад. Використовуючи клас Dog, створіть трьох нових собак різного
віку. Потім напишіть функцію під назвою get_biggest_number (), яка приймає
будь-яку кількість аргументів (* args) і повертає найбільший. Потім виведіть вік
найстаршого собаки так:
The oldest dog is 7 years old.

class Dog:

9
# Class Attribute
species = 'mammal'

# Initializer / Instance Attributes


def __init__(self, name, age):
self.name = name
self.age = age

# Instantiate the Dog object


jake = Dog("Jake", 7)
doug = Dog("Doug", 4)
william = Dog("William", 5)

# Determine the oldest dog


def get_biggest_number(*args):
return max(args)

# Output
print("The oldest dog is {} years old.".format(
get_biggest_number(jake.age, doug.age, william.age)))

Ще раз про параметр self


Кожен клас повинен мати метод із спеціальним іменем __init__. Цей метод
ініціалізатора автоматично викликається кожного разу, коли створюється новий
екземпляр класу. Це дає програмісту можливість встановити необхідні
атрибути в новому екземплярі, надавши їм їх початковий стан / значення.
Параметр self (можна вибрати будь-яке інше ім'я, але self - це угода)
автоматично встановлюється для посилання на щойно створений об'єкт, який
потрібно ініціалізувати.

Практичні завдання
Завдання 1. Вибрати предметну область для створення класу відповідно до
номера прізвища в журналі:
1. транспорт; 7. дерева; 13. котячі;
2. птахи; 8. чотирикутники; 14. спортивні ігри;
3. квіти; 9. автомобілі; 15. плазуни;
4. трикутники; 10. домашні улюбленці; 16. смартфони;
5. роботи; 11. фрукти; 17. динозаври.
6. риби; 12. комп’ютерні ігри;
10
Завдання 2. Створити клас, описати метод __init __ (), в якому
ініціалізувати (вказати) три властивості (атрибути) об'єкта. Для
властивостей використати мінімум 2 типи даних, наприклад, рядковий та
цілочисловий.
Завдання 3. Створити 5 об’єктів класу. Вивести на екран значення
властивостей для кожного об’єкта.
Завдання 4. Визначити атрибут класу. Створити умовний оператор, який
перевіряє наявність цього атрибуту в одного з об’єктів класу.
Завдання 5. Створити функцію, яка визначає найменше значення
властивості (з числовим значенням) серед усіх ініціалізованих об’єктів
класу.

Контрольні запитання
1. Назвіть суть об’єктно-орієнтованого програмування.
2. Що в програмуванні називається класом?
3. Як між собою пов’язані клас та об’єкт (екземпляр класу)?
4. Для чого призначений метод __init__(), або конструктор класу? Чи є він
обов’язковим методом класу?
5. Яку мінімальну кількість параметрів повинен мати метод __init__()? Яке
призначення параметра self?
6. Як створити об’єкти класу? Як вивести на екран значення властивості
об’єкта?
7. Нехай задано клас:
class MyClass:
x = 5

 вкажіть оператор, за домогою якого можна створити об’єкт класу і


зберегти його у змінній p;
 вкажіть оператор, за домогою якого можна вивести на екран
значення властивості x об’єкта p.
8. Нехай задано клас та екземпляр класу:

class Person:
degree = "bachelor"
def __init__(self, name, surname, salary):
self.name = name
self.surname = surname
self.salary = salary
person = Person("Jane", "Doe", 12000)

11
 Поясніть, для чого призначені та що зберігають наступні змінні:
Person
person
surname
self
salary
degree

 Поясніть відмінність між атрибутами name та degree.

Тема №2. Методи


Мета: формування вмінь створення методів класів та застосування їх до
об’єктів.
Теоретичні питання
План
1. Поняття методу в ООП.
2. Створення та використання методів.

1. Поняття методу в ООП.


Метод в ООП – це функція, яка визначена всередині опису класу і може
бути викликана для екземплярів цього класу.
Методи екземплярів викликаються для виконання операцій з атрибутами
об'єктів. Як і для методу __init__, першим аргументом завжди є self:

class Dog:
# Class Attribute
species = 'mammal'

# Initializer / Instance Attributes


def __init__(self, name, age):
self.name = name
self.age = age

# instance method
def description(self):
return "{} is {} years old".format(self.name,
self.age)

# instance method
12
def speak(self, sound):
return "{} says {}".format(self.name, sound)

# instance method
def eat(self, food):
return "{} eats {}".format(self.name, food)

# Instantiate the Dog object


philo = Dog("Philo", 5)
mikey = Dog("Mikey", 6)

# call our instance methods


print(mikey.description())
print(mikey.speak("Gruff Gruff"))
print(philo.description())
print(philo.eat("bones"))

2. Створення та використання методів.


Визначимо клас Point:

class Point:
""" Point class represents and manipulates x,y
coords. """

def __init__(self, x=0, y=0):


""" Create a new point at x, y """
self.x = x
self.y = y

Створимо об’єкти класу:

p = Point(3, 4)
q = Point(6, 3)
r = Point() # r represents the origin (0, 0)
print(p.x, q.y, r.x)

Наступна діаграма демонструє результат виконання оператора щодо


створення екземпляра p:

13
Змінна p посилається на об'єкт Point, який містить два атрибути. Кожен
атрибут посилається на число. Доступ до значення атрибута можна отримати,
використовуючи оператор p.x.
Додавання інших методів до класу
Створимо метод distance_from_origin для обчислення відстані від
початку координат до точки:

def distance_from_origin(self):
""" Compute my distance from the origin """
return ((self.x ** 2) + (self.y ** 2)) ** 0.5

Застосуємо створений метод до об’єктів:

print(p.distance_from_origin())
print(q.distance_from_origin())
print(r.distance_from_origin())

Об’єкти як аргументи (параметри)


Розглянемо просту функцію, аргументом якої є об’єкт Point :

def print_point(pt):
print("({0}, {1})".format(pt.x, pt.y))

Виклик функції:

p.print_point()
q.print_point()
r.print_point()

Перетворення екземпляра в рядок


Для виведення значень атрибутів об’єкта на екран необхідно мати метод,
за допомогою якого об’єкт міг би створювати рядкове подання самого себе:

def __str__(self):
return "({0}, {1})".format(self.x, self.y)

Виклик методу:
print(p)

Об’єкти як значення, що повертаються функціями


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

def midpoint(p1, p2):


14
""" Return the midpoint of points p1 and p2 """
mx = (p1.x + p2.x)/2
my = (p1.y + p2.y)/2
return Point(mx, my)

Виклик функції:
m = Point.midpoint(p,q)
print(r)

Тепер оформимо це як метод:

def halfway(self, target):


""" Return the halfway point between myself and
the target """
mx = (self.x + target.x)/2
my = (self.y + target.y)/2
return Point(mx, my)

Виклик методу:
m = p.halfway(q)
print(r)

або
print(Point(3, 4).halfway(Point(5, 12)))

Практичні завдання
Завдання 1. Розробити метод reflect_x у класі Point, що повертає нову
точку, яка є відображенням заданої точки відносно вісі x. Нехай
визначено клас Point:

class Point:
""" Point class represents and manipulates x,y coords.
"""

def __init__(self, x=0, y=0):


""" Create a new point at x, y """
self.x = x
self.y = y

Та створені об’єкти класу:

p = Point(3, 4)

15
q = Point(6, 3)
r = Point()

Завдання 2. Розробити метод reflect_x у класі Point, що повертає нову


точку, яка є відображенням заданої точки відносно вісі x.
Наприклад, Point(3, 5).reflect_x() є (3, -5)
Завдання 3. Розробити метод slope_from_origin у класі Point, що
повертає коефіцієнт прямої, яка проходить через початок координат та
задану точку. Наприклад, Point(4,10).slope_from_origin() є 2.5
Завдання 4. Рівняння прямої – "y = kx + b". Коефіцієнти k і b повністю
описують лінію. Розробити метод get_line_to у класі Point, що повертає
коефіцієнти k і b прямої, яка проходить через точку-екземпляр та надану
точку. Наприклад,
Point(4, 11).get_line_to(Point(6, 15)) є (2,3).
Завдання 5. Розробити метод description(self) та ще два методи для
своєї предметної області

Контрольні запитання
1. Що в об’єктно-орієнтованому програмуванні називається методом?
2. Як викликати метод для об’єкта?
3. У чому полягають відмінності між методом класу та функцією?
4. Нехай задано клас та екземпляр класу:
class Snake:
def __init__(self, name):
self.name = name

def change_name(self, new_name):


pass
python = Snake("python")

 Замість слова pass запишіть оператори метода change_name(), за


домогою якого можна змінити значення властивості name;
 укажіть оператор, за домогою якого можна застосувати метод
change_name() до об’єкта python і змінити значення властивості
name на "anaconda"

5. Нехай задано клас та екземпляр класу:


class Person:
16
degree = "bachelor"
def __init__(self, name, surname, salary):
self.name = name
self.surname = surname
self.salary = salary

def salary_increase(self, interest):


self.salary += (self.salary * interest)/100
return self.salary

person = Person("Jane", "Doe", 12000)


person.salary_increase(10)
print(person.salary)

Поясніть, для чого призначений метод salary_increase() та що буде


виведено в результаті роботи програми.

Тема №3. Наслідування


Мета: формування вмінь створення класів і об’єктів, визначення
властивостей об’єктів та атрибутів класу.
Теоретичні питання
План
1. Поняття наслідування в ООП.
2. Створення дочірніх класів та використання наслідування.

1. Поняття наслідування в ООП.


Наслідування – це процес, за допомогою якого один клас успадковує
атрибути та методи іншого класу. Новостворені класи називаються дочірніми
класами, а класи, з яких походять дочірні класи, називаються батьківськими
класами.
Це схоже на спадкування у живих істот. Наприклад, у людей одна
людина набуває властивостей іншої людини шляхом наслідування. Тобто
дитина набуває певних властивостей своїх батьків завдяки наслідуванню, а
також має власні властивості.
АБО
Син / дочка отримує багатство від своїх батьків, бабусь і дідусів тощо.
Багатство передається з покоління в покоління.
Аналогічно, в об'єктно-орієнтованому програмуванні властивості від
одного класу до іншого класу передаються до тих пір, поки продовжується
наслідування.
Базовий клас – це клас, який, як правило, всі інші класи успадковують
як батьківський.
17
Приклади наслідування представлені на рис. 1.4 – 1.6.

Рис. 1.3. Наслідування. Базовий клас Shapes

Рис. 1.4. Наслідування. Базовий клас Vehicle

Рис. 1.5. Наслідування. Базовий клас Mammals

18
2. Створення дочірніх класів та використання наслідування.
Додамо до класу Dog два дочірні класи:

# Child class (inherits from Dog class)


class RussellTerrier(Dog):
def run(self, speed):
return "{} runs {}".format(self.name, speed)

# Child class (inherits from Dog class)


class Bulldog(Dog):
def run(self, speed):
return "{} runs {}".format(self.name, speed)

Створимо новий об’єкт, переконаємося, що він наслідує атрибути та


методи батьківського класу:

jim = Bulldog("Jim", 12)


print(jim.description())

Переконаємося, що новий об’єкт має власні атрибути та методи:

print(jim.run("slowly"))

Використання функції isinstance для перевірки наслідування.


Чи наслідує jim клас Dog()?

print(isinstance(jim, Dog))

Чи наслідує julie клас Dog()?

julie = Dog("Julie", 100)


print(isinstance(julie, Dog))

Чи наслідує johnny walker клас Bulldog ()?

johnnywalker = RussellTerrier("Johnny Walker", 4)


print(isinstance(johnnywalker, Bulldog))

Чи наслідує julie jim-а?

print(isinstance(julie, jim))

19
Перевірка чи є julie экземпляром jim неможлива, оскільки jim є
екземпляром класу, а не самим класом. Отримується повідомлення про
помилку - TypeError.

Зміна функціональності батьківського класу


Можна змінити функціональність батьківського класу. Тобто дочірні
класи можуть замінити атрибути та поведінку батьківського класу.
Наприклад.
Пам’ятаємо, що

class Dog:
... species = 'mammal'

Опишемо ще два дочірні класи:

class SomeBreed(Dog):
... pass
...
class SomeOtherBreed(Dog):
... species = 'reptile'

Створимо два екземпляри описаних класів та виведем на екран значення


атрибута класу species:

frank = SomeBreed()
print(frank.species)
beans = SomeOtherBreed()
print(beans.species)

Результати:

'mammal'
'reptile'

Додавання до дочірнього класу нових атрибутів


Нехай до класу Bulldog необхідно додати атрибут weight (вага).
Спочатку використаємо функцію super(), яка змусить дочірній клас
наслідувати всі методи та властивості від батьківського класу, а потім додамо
атрибут weight:

class Bulldog(Dog):
def __init__(self, name, age, weight):
super().__init__(name, age)
self.weight = weight
20
Також до класу Bulldog додамо метод welcome(), який надасть змогу
сформувати запрошення на змагання:

def welcome(self):
return "{} is {} and his weight is {} kg. \
Welcome to the competition".format(self.name, self.age,
self.weight)

Тоді створення об’єкта та виклик методу є таким:

jim = Bulldog("Jim", 12, 27)


print(jim.description())

print(jim.welcome())

Практичні завдання

Завдання 1. Створити систему класів

Triangle

EquiTriangle(Triangle) RightTriangle(Triangle)

Завдання 2. У класі Triangle розробити методи:


a. виводить повідомлення it's just a triangle
b. знаходить периметр трикутника
c. знаходить площу за формулою Герона
Завдання 3. У класі EquiTriangle розробити методи:
d. виводить повідомлення it's an equilateral triangle
e. знаходить площу за формулою для рівностороннього
трикутника
Завдання 4. У класі RightTriangle розробити методи:
f. виводить повідомлення it's a right triangle
g. знаходить площу за формулою для прямокутного трикутника за
двома катетами
Завдання 5. Створити три об’єкти (по одному кожного класу).
21
Завдання 6. Застосувати розроблені методи до об’єктів (урахувати
наслідування).
Завдання 7. До двох створених об’єктів застосувати функцію
isinstance() для з’ясування приналежності об’єктів до певного класу.
Завдання 8. Для своєї предметної області створити два дочірніх класи.
Нехай екземпляри дочірніх класів містять нову властивість. Розробити
методи для цих класів. Застосувати розроблені методи до об’єктів
(урахувати наслідування).

Контрольні запитання
1. Назвіть суть процесу наслідування в об’єктно-орієнтованому
програмуванні.
2. Які класи називаються батьківськими, а які дочірніми?
3. Як створити дочірній клас?
4. Для чого призначена функція isinstance()? Які її аргументи? Чи
можуть бути аргументами цієї функції два екземпляри класу?
5. Чи можуть дочірні класи замінювати атрибути та поведінку батьківського
класу?
6. Запишіть програмний код для створення класу з іменем Student, який
наслідує властивості та методи класу Person?
7. Нехай задано класи та екземпляр:

class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname

def printname(self):
print(self.firstname, self.lastname)

class Student(Person):
def __init__(self, fname, lname, year):
super().__init__(fname, lname)
self.graduationyear = year

def welcome(self):
print("Welcome", self.firstname, self.lastname,
"to the class of", self.graduationyear)

x = Student("Mike", "Olsen", 2019)


x.welcome()

22
Поясніть:
 який клас є батьківським, а який дочірнім?
 для чого в класі Student використано функцію super()?
 що буде виведено на екран у результаті виконання програмного коду?
 чи можна застосувати метод welcome() до об’єктів класу Person?
 чи можна застосувати метод printname() до об’єктів класу Student?

Тема № 4. Поліморфізм
Мета: формування вмінь створення та використання поліморфних класів.

План
1. Поняття поліморфізму в ООП.
2. Поліморфізм у Python.
3. Використання поліморфізму в класах.

1. Поняття поліморфізму в ООП.


Поліморфізм (з грец. πολύς «багато» + μορφή «форма») – концепція в
програмуванні, завдяки якій можна опрацьовувати об’єкти по-різному
залежно від їх класу.
Поліморфізм - це виконання методом з одним тим самим іменем різних
дій залежно від приналежності до того чи іншого класу.
Поліморфізм забезпечує гнучкість і слабкий зв’язок, завдяки чому код
можна розширювати і легко підтримувати.
Поліморфізм може здійснюватися через наслідування, підкласи
використовують методи базового класу або перевизначають їх.

2. Поліморфізм у Python
У Python багато операторів мають властивість поліморфізму.
Поліморфізм оператора додавання:

num1 = 1
num2 = 2
print(num1+num2)

Результат:
3

str1 = "Python"
str2 = "Programming"
print(str1+" "+str2)

Результат:
23
Python Programming

Той самий оператор виконує різні дії для даних різних типів.

Поліморфізм функцій:

l = [1, 2, 3, 4, 5]
length = len(l)
print(length)

s = "Python Programming"
length = len(s)
print(length)

d = {1: "Archie", 2: "Brady", 3: "Charlie"}


length = len(d)
print(length)

Результати:
5
18
3

Багато типів даних, такі як рядок, список, кортеж, множина та словник


можуть працювати з функцією len(). Однак ми бачимо, що ця функція
повертає конкретну інформацію про конкретні типи даних (рис. 1.7).

Рис. 1.7. Перезавантаження стандартної функції len()

24
Це був загальний погляд на поліморфізм та його реалізацію в мові
Python. Розглянемо поліморфізм у визначених користувачем методах.

3. Використання поліморфізму в класах

Python використовує так звану «качину типізацію». Термін «качина


типізація» походить від цитати письменника Джеймса Віткомба Райлі: "Коли
я бачу птаха, який ходить як качка, плаває як качка, крякає як качка, я
називаю цю птицю качкою". Використання качиної типізації пов’язане із
встановленням придатності об'єкта для конкретної мети. При використанні
звичайної типізації ця придатність визначається лише типом об'єкта, але при
качиній типізації наявність методів та властивостей використовується для
визначення придатності, а не фактичного типу об'єкта, про який йдеться.
Тобто, ви перевіряєте, чи об’єкт крякає як качка і ходить як качка, а не
запитує, чи є об’єкт качкою.
Коли декілька класів або підкласів мають однакові імена методів, але
різні реалізації для цих самих методів, класи є поліморфними, оскільки вони
використовують єдиний інтерфейс для використання з об'єктів різних типів.
Функція зможе оцінити ці поліморфні методи, не знаючи, об’єкти яких класів
викликаються (рис. 1.8).

Рис. 1.8. Сутність поліморфізму

Для класу Dog було:

25
class Dog:
def __init__(self, name, age):
def description(self):
def speak(self, sound):
def eat(self, food):

class RussellTerrier(Dog): class Bulldog(Dog):


def run(self, speed): def run(self, speed):

Створимо поліморфні класи:

class Dog:
def __init__(self, name, age):
def description(self):
def speak(self):
def eat(self):
def run(self):

class RussellTerrier(Dog): class Bulldog(Dog):


def speak(self): def speak(self):
def eat(self): def eat(self):
def run(self): def run(self):

Відкрити програму class_dog_polymorphism.py

4. Використання поліморфізму в програмах.


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

for dog in (bobick, jim, cookie):


print()
print(dog.description())
print(dog.speak())
print(dog.eat())

26
print(dog.run())

Поліморфізм з функцією
Ми також можемо створити функцію, яка може приймати будь-який
об’єкт з урахуванням поліморфізму:

def in_the_park(dog):
print(dog.description())
print(dog.speak())
print(dog.eat())

in_the_park(jim)
in_the_park(cookie)

Приклад 2. Створити програму для малювання, яка опрацьовує


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

import math

class Circle():
def __init__(self, x = 0.0, y = 0.0, radius = 1.0):
self.x = x
self.y = y
self.radius = radius

def computeArea(self):
return math.pi * self.radius ** 2

def computePerimeter (self):


return 2 * math.pi * self.radius

def move(self, deltaX, deltaY):


self.x += deltaX
self.y += deltaY

def __str__(self):
return "Circle with coordinates {}, {} and radius
{}".format(self.x,
self.y, self.radius)

27
class Rectangle():
def __init__(self, x = 0.0, y = 0.0, width = 1.0,
height = 1.0):
self.x = x
self.y = y
self.width = width
self.height = height

def computeArea(self):
return self.width * self.height

def computePerimeter (self):


return 2 * (self.width + self.height)

def move(self, deltaX, deltaY):


self.x += deltaX
self.y += deltaY

def __str__(self):
return "Rectangle with coordinates {}, {}, \
width {} and height {}".format(self.x, self.y,
self.width, self.height )

Створимо відповідні об’єкти та застосуємо поліморфні методи:

circle1 = Circle(10,4,3)
print(circle1)
print("The circle1's area is
{:.3f}".format(circle1.computeArea()))
circle1.move(3,-1)
print(circle1)

rectangle1 = Rectangle(10,10,3,2)
print(rectangle1)
print("The rectangle1's area is
{:.3f}".format(rectangle1.computeArea()) )
rectangle1.move(2,2)
print(rectangle1)

Результати:

Circle with coordinates 10, 4 and radius 3


The circle1's area is 28.274
Circle with coordinates 13, 3 and radius 3
28
Rectangle with coordinates 10, 10, width 3 and height 2
The rectangle1's area is 6.000
Rectangle with coordinates 12, 12, width 3 and height 2

Застосуємо наслідування

Клас Geometry буде абстрактним класом в тому сенсі, що він не


призначений для створення об'єктів з. Його мета - представити властивості та
шаблони для методів, спільних для всіх геометричних класів нашого проекту.
Програмний код стане таким:

import math

class Geometry():

def __init__(self, x = 0.0, y = 0.0):


self.x = x
self.y = y

def computeArea(self):
pass

def computePerimeter(self):
pass

def move(self, deltaX, deltaY):


self.x += deltaX
self.y += deltaY

def __str__(self):
return "Abstract class Geometry should not be
instantiated and \
derived classes should override this method!"

class Circle(Geometry):

def __init__(self, x = 0.0, y = 0.0, radius = 1.0):

29
super(Circle,self).__init__(x,y)
self.radius = radius

def computeArea(self):
return math.pi * self.radius ** 2

def computePerimeter (self):


return 2 * math.pi * self.radius

def __str__(self):
return "Circle with coordinates {}, {} and radius
{}".format(self.x,
self.y, self.radius)

class Rectangle(Geometry):

def __init__(self, x = 0.0, y = 0.0, width = 1.0,


height = 1.0):
super(Rectangle, self).__init__(x,y)
self.width = width
self.height = height

def computeArea(self):
return self.width * self.height

def computePerimeter (self):


return 2 * (self.width + self.height)

def __str__(self):
return "Rectangle with coordinates {}, {}, \
width {} and height {}".format(self.x, self.y,
self.width, self.height )

circle1 = Circle(10,4,3)
print(circle1)
print("The circle1's area is
{:.3f}".format(circle1.computeArea()))
circle1.move(3,-1)
print(circle1)

rectangle1 = Rectangle(10,10,3,2)
print(rectangle1)
print("The rectangle1's area is
{:.3f}".format(rectangle1.computeArea()) )
rectangle1.move(2,2)
30
print(rectangle1)

Результати не змінилися, але програмний код є зрозумілішим

До ієрархії класів додамо ще один клас – Square:

Новий клас Square – це дочірній клас класу Rectangle (Rectangle є його


базовим класом), але опосередковано він є підкласом класу Geometry.
До програми додамо код створення класу Square та об’єкта цього класу:

class Square(Rectangle):

def __init__(self, x = 0.0, y = 0.0, sideLength =


1.0):
super(Square,self).__init__(x, y, sideLength,
sideLength)

def __str__(self):
return 'Square with coordinates {}, {} \
and sideLength {}'.format(self.x, self.y, self.width )

square1 = Square(5, 5, 8)
print(square1)
print("The square1's area is
{:.3f}".format(square1.computeArea()))
print("The circle1's Perimeter is
{:.3f}".format(square1.computePerimeter()))
square1.move(2,2)
print(square1)

Для класу Square визначається лише новий конструктор, який приймає


координати x, y та значення однієї сторони sideLength, а не значення
ширини та висоти. При використанні функції super() значення sideLength
надається як параметру ширини, так і параметру висоти. Змінюється метод
31
__str __ (), для виведення повідомлення про квадрат можна використати
self.width або self.height. Реалізації методів computeArea() та
computePerimeter() наслідується від класу Rectangle, а реалізація
методу move() опосередковано від класу Geometry.
Нехай необхідно обчислити загальну площу фігур, розташованих,
наприклад, на ігровому екрані. Створимо функцію computeTotalArea(), яка
обчислює загальну площу:

def computeTotalArea(geometryLayer):
area = 0
for geom in geometryLayer:
area += geom.computeArea()
return area

layer=[circle1, rectangle1, square1, Circle(3,3,9),


Square(30,20,5)]

print("The Total Area is


{:.3f}".format(computeTotalArea(layer)))

Практичні завдання

Завдання 1. Для прикладу з трикутниками (див. лаб. роботу №3)


розробити поліморфні класи з методами:
h. draw(self) виводить повідомлення про побудову трикутника
i. line_width(self) виводить повідомлення про товщину лінії
j. fill(self) виводить повідомлення про колір зафарбування
трикутника.
Завдання 2. Для прикладу з колами та прямокутниками додати дочірній
клас, що надасть можливість створювати правильні шестикутники (або
п’ятикутники, або восьмикутники).
Завдання 3. Для своєї предметної області розробити дочірні поліморфні
класи. Створити функцію (поза класами), що послідовно опрацьовує
створені об’єкти (аналогічно до def in_the_park(dog)).

32
Контрольні запитання
6. Назвіть суть поліморфізму в об’єктно-орієнтованому програмуванні.
7. Як проявляється поліморфізм в операторі додавання?
8. Як проявляється поліморфізм у функції len(l)?
9. Як відбувається використання поліморфізму в класах? Які класи можна
назвати поліморфними?
10.Чи можна назвати наведені класи поліморфними:

class India():
def capital(self):
print("New Delhi is the capital of India.")

def language(self):
print("Hindi is the most widely spoken language
of India.")

def type(self):
print("India is a developing country.")

class USA():
def capital(self):
print("Washington, D.C. is the capital of USA.")

def language(self):
print("English is the primary language of USA.")

def type(self):
print("USA is a developed country.")

obj_ind = India()
obj_usa = USA()
for country in (obj_ind, obj_usa):
country.capital()
country.language()
country.type()

Якщо так, то чому? Чи використовується тут наслідування? Що буде


виведено на екран у результаті виконання наведеного коду?

11.Нехай задано класи та екземпляри класів:

class Bird:
def intro(self):
print("There are many types of birds.")
33
def flight(self):
print("Most of the birds can fly but some cannot.")

class Sparrow(Bird):
def flight(self):
print("Sparrows can fly.")

class Ostrich(Bird):
def flight(self):
print("Ostriches cannot fly.")

def my_birds(bird):
bird.intro()
bird.flight()

obj_bird = Bird()
obj_spr = Sparrow()
obj_ost = Ostrich()

my_birds(obj_bird)
my_birds(obj_spr)
my_birds(obj_ost)

Поясніть:
чи використовується тут наслідування?
які методи є поліморфними?
що буде виведено на екран у результаті виконання програмного коду?

34
Тема № 5 Перезавантаження операторів, методів та функцій
Мета: формування вмінь перезавантаження операторів, методів та функцій
План
1. Поняття перезавантаження в програмуванні.
2. Модель даних у Python.
3. Перезавантаження деяких функцій та методів.
4. Перезавантаження деяких операторів.

1. Поняття перезавантаження в програмуванні

Overriding vs Overloading
Перевизначення (Overriding) методу:
Перевизначення методу – використання методу з однаковим іменем і
однаковими аргументами. Реалізується з наслідуванням. Розглядали в темі
Поліморфізм.
Перезавантаження (Overloading) методу:
Перезавантаження методу – використання методу з однаковим іменем і
різними аргументами.
Відмінність аргументів базується на кількості та типах аргументів.
Процес перезавантаження використовується в одному класі.
Сутність перезавантаження операторів полягає в тому, що один й той
самий оператор демонструє різну поведінку для об’єктів різних класів.
Перезавантаження (Overloading) – це здатність метода, функції або
оператора поводитися по-різному в залежності від параметрів, які
передаються, або операндів, на які діє оператор. Наприклад, оператори + та *
демонструють різну поведінку для об’єктів класу str та об’єктів класів int
або float:

>>> 1 + 2
3
>>> 'hello ' + 'friends'
'hello friends'
>>> 3 * 2
6
>>> 'friends' * 3
'friendsfriendsfriends'

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


задано клас та об’єкт:

class Arithmetic:
def add(self, a, b):
35
return a + b
def add(self, a, b, c):
return a + b + c

obj = Arithmetic()
print(obj.add(12,14))

Результат – повідомлення про помилку:

Traceback (most recent call last):


File "D:\Python37-32\classes_objects\test.py", line 8,
in <module>
obj.add(12,14)
TypeError: add() missing 1 required positional argument:
'c'

У такому поданні Python не допускає перезавантаження методів. Коли


створюється кілька методів з одним тим самим іменем, але з різною
кількістю аргументів, Python запам'ятовує та дає можливість
використовувати останній описаний метод. Такий виклик не дає помилки:

print(obj.add(12,14,170))
Результат:
196

Щоб перезавантажити користувацький метод, необхідно написати його


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

class Student:
def hello(self, name=None):
if name is not None:
print('Hey ' + name)
else:
print('Hey ')

# Creating a class instance


std = Student()

# Call the method


std.hello()

# Call the method and pass a parameter


std.hello('Nicholas')
36
Результати:
Hey
Hey Nicholas

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


виклику.
Тобто перезавантаження передбачає роботу методу, як показано на схемі
(рис. 1.9):

Рис. 1.9. Сутність перезавантаження методу

Тоді метод add() класу Arithmetic можна записати так:

class Arithmetic:
def add(self, a=None, b=None, c=None):
# When three params are passed
if a!=None and b!=None and c!=None:
s = a + b + c
return s
# When two params are passed
elif a!=None and b!=None:
s = a + b
return s

obj = Arithmetic()
print(obj.add(12,14))
print(obj.add(12,14,15))

або

class Arithmetic:
def add(self, *args):
37
print(args)
total = 0
for i in args:
print(total)
total += i
return total

obj = Arithmetic()
print(obj.add(17,18,19,20,21))

Деякі переваги використання перезавантаження:


− перезавантаження методу сприяє повторному його використанню;
замість написання кількох методів, які незначно відрізняються,
можна написати один метод і перезавантажити його;
− перезавантаження усуває складність коду.
Використання перезавантаження є корисним. Однак воно має ряд
недоліків.
Розглянемо, як це можна реалізувати для власних класів та об’єктів.

2. Модель даних у Python

Нехай є клас, який представляє онлайн-замовлення, що має атрибути:


кошик (list) і покупец (string). Якщо необхідно отримати довжину списку
кошика, то можна налаштувати вбудовану функцію len() так, щоб вона
повертала довжину списку кошика для об'єкта. Також необхідно мати
можливість додавати товари до кошика. Можна налаштувати оператор + так,
щоб він додавав новий товар в корзину.
Python робить все це за допомогою спеціальних методів. Ці спеціальні
методи мають угоду про імена, де ім'я починається з двох підкреслень, після
яких йде ідентифікатор, і закінчується двома підкресленнями.
По суті, кожній вбудованій функції чи оператору відповідає спеціальний
метод. Наприклад, __len__() відповідає len(), __add__() відповідає
оператор +. Такі методи називають магічними.
За замовчуванням більшість вбудованих функцій і операторів не будуть
працювати з об'єктами користувацьких класів. Необхідно додати відповідні
спеціальні методи у визначення класу, щоб зробити ваш об'єкт сумісним з
вбудованими функціями і операторами. Тоді поведінка функції або оператора
змінюється відповідно до визначеного в методі.
Модель даних (Розділ 3 документації Python
https://docs.python.org/3/reference/datamodel.html ) містить всі доступні
спеціальні методи і надає засоби перезавантаження вбудованих функцій і
операторів, щоб ви могли використовувати їх в своїх власних об'єктах.

38
3. Перезавантаження деяких функцій
Перезавантаження функції len()
Кожний клас в Python визначає свою поведінку для вбудованих функцій
і методів.
Коли викликається функція len(), Python опрацьовує виклик як
obj.__len__():

>>> a = 'Black and White Night'


>>> len(a)
21
>>> a.__len__()
21

При використанні оператора [] для ітераційного об’єкта, щоб отримати


значення за заданим індексом, Python обробляє цей оператор як itr .__
getitem __ (index), де itr є ітерабельним об'єктом, а index - індексом,
значення за яким необхідно отримати:

>>> b = ['Black', 'and', 'White', 'Night']


>>> b[0]
'Black'
>>> b.__getitem__(0)
'Black'

Список усіх методів і функцій для об’єкта класу str можна отримати за
допомогою функції dir()
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__',
'__dir__', '__doc__', '__eq__', 'rstrip',

'split', 'splitlines', 'startswith', 'strip', 'swapcase',
'title', 'translate', 'upper', 'zfill']

Для перезавантаження функції len() необхідно визначити спеціальний


метод __len__() у власному класі:

class Order:
def __init__(self, cart, customer):
self.cart = list(cart)
self.customer = customer

def __len__(self):
return len(self.cart)

39
order = Order(['banana', 'apple', 'mango'], 'Alice
Jones')
print(len(order))

Результат:
3

Якщо не перезавантажити метод __len__(), але викликати len() для


створеного об’єкту, то отримується повідомлення про помилку TypeError.
(Закоментувати __len__)
При перезавантаженні len() слід пам’ятати, що функція повинна
повертати ціле число, інакше отримується повідомлення про помилку
TypeError:

def __len__(self):
return float(len(self.cart))

Перезавантаження функції abs()


При перезавантаженні функції abs() немає обмежень для типу
значення, що повертає ця функція. У класі, який представляє вектор у
двовимірному просторі, abs() призначена для обчислення довжини вектора:

class Vector:
def __init__(self, x, y):
self.x = x
self.y = y

def __abs__(self):
return (self.x ** 2 + self.y ** 2) ** 0.5

vector = Vector(3, 4)
print(abs(vector))

Результат:
5.0

Виведення на екран даних про об’єкт


Метод __str__() використовується для зручного рядкового подання
об’єкту. Можна задати формат виведення відповідним чином визначивши
метод __str__() у класі.
Виведемо на екран Vector-об’єкт у форматі xi+yj :

class Vector:
def __init__(self, x, y):
40
self.x = x
self.y = y

def __str__(self):
return '{}i+{}j'.format(self.x, self.y)

vector = Vector(3, 4)
print(str(vector))

Метод __str__() повертає тільки рядок.

Подання об’єктів за допомогою методу __repr__():


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

def __repr__(self):
return 'Vector({}, {})'.format(self.x, self.y)

vector = Vector(3, 4)

print(repr(vector))

Метод __repr__() можна використовувати, коли об’єкти об’єднані в


список.

Перезавантаження функції bool()


Вбудована функція bool() використовується для визначення логічного
значення об’єкта.
Перезавантажимо функцію bool() для Order- класу. Опрацьовувати
замовлення, якщо довжина списку кошику не дорівнює нулеві:

class Order:
def __init__(self, cart, customer):
self.cart = list(cart)
self.customer = customer

def __len__(self):
return len(self.cart)

def __bool__(self):
return len(self.cart)>0

41
order1 = Order(['banana', 'apple', 'mango'], 'Alice
Jones')
order2 = Order([], 'Tom Brooks')

print(bool(order1))
print(bool(order2))

Додати
for order in [order1, order2]:
if order:
print("{}'s order is
processing...".format(order.customer))
else:
print("Empty order for customer
{}".format(order.customer))

4. Перезавантаження операторів
Здійснити перезавантаження операторів можна так само як і
перезавантаження функцій.

Перезавантаження оператора +
Оператор + можна перезавантажити за допомогою спеціального методу
__add__(). Реалізуємо можливість додавати нові товари в корзину в Order-
класі. Нехай метод __add__() повертає новий Order-об’єкт, до якого внесені
зміни:

class Order:
def __init__(self, cart, customer):
self.cart = list(cart)
self.customer = customer

def __add__(self, other):


new_cart = self.cart.copy()
new_cart.append(other)
return Order(new_cart, self.customer)

order1 = Order(['banana', 'apple', 'mango'], 'Alice


Jones')
order2 = Order([], 'Tom Brooks')

order2 = order2 + 'orange'


print(order2.cart)

order2 = order2 + 'kiwi'


42
print(order2.cart)

Оператор +=
Оператор += є коротним варіантом для виразу obj1 = obj1 + obj2.
Спеціальним методом, що відповідає йому, є __iadd__(). Метод
__iadd__() повинен вносити зміни безпосередньо в аргумент self і
повертати результат, який може бути або не бути self. Ця поведінка сильно
відрізняється від __add__(), оскільки останній створює новий об'єкт і
повертає його, як бачимо вище.
Використання += для двох об'єктів еквівалентно таким операторам:

>>> result = obj1 + obj2


>>> obj1 = result

Зробимо можливим використання оператора += для класу Order, щоб


нові товари можна було додавати до кошика за допомогою +=:

class Order:
def __init__(self, cart, customer):
self.cart = list(cart)
self.customer = customer

## def __add__(self, other):


## new_cart = self.cart.copy()
## new_cart.append(other)
## return Order(new_cart, self.customer)

def __iadd__(self, other):


self.cart.append(other)
return self

order1 = Order(['banana', 'apple', 'mango'], 'Alice


Jones')
order2 = Order([], 'Tom Brooks')

##order2 = order2 + 'orange'


##print(order2.cart)
##order2 = order2 + 'kiwi'
##print(order2.cart)

order2 += 'orange'
print(order2.cart)
order2 += 'kiwi'
43
print(order2.cart)

Будь-яка зміна вноситься через self потім повертається результат.

Практичні завдання

Завдання 1. Знайти в інтернеті відомості про метод __repr__().


З’ясувати відмінності між методами __str__() та __repr__(). Навести
приклади.
Завдання 2. Для своєї предметної області в один із створених класів
додати перезавантажену вбудовану функцію (для прикладу див.
перезавантаження функцій abs() та bool() в лекції).
Завдання 3. Знайти в інтернеті теоретичні відомості і приклади
перезавантаження операторів:
а) віднімання (Subtraction, p1 - p2, p1.__sub__(p2))
б) множення (Multiplication, p1 * p2, p1.__mul__(p2)).
Завдання 4. Для своєї предметної області в один із створених класів
додати перезавантажений оператор (додавання, віднімання, множення,
ділення).

Контрольні запитання
1. Назвіть суть перезавантаження операторів в об’єктно-орієнтованому
програмуванні.
2. Як проявляється перезавантаження в операторі додавання?
3. У чому полягає відмінність між перевизначенням (Overriding) та
перезавантаженням (Overloading) методів?
4. Які переваги надає використання перезавантаження?
5. Якщо l – це список, то чи однаковими є оператори len(l) та
l.__len__()?
6. Чи можна сказати, що відбулося перезавантаження методу area():

class Compute:

# area method
def area(self, x = None, y = None):

if x != None and y != None:


return x * y

elif x != None:
return x * x
44
else:
return 0

# object
obj = Compute()

# zero argument
print("Area:", obj.area())

# one argument
print("Area:", obj.area(2))

# two argument
print("Area:", obj.area(4, 5))

Якщо так, то чому?

7. Нехай задано класи та екземпляри класів:

class Bubble:
def __init__(self, volume):
self.volume = volume

b1 = Bubble(20)
b2 = Bubble(30)

print(b1 + b2)

Що буде виведено на екран у результаті виконання програмного коду?

8. Нехай до класу Bubble додано вбудований метод __str__()

class Bubble:
def __init__(self, volume):
self.volume = volume

def __str__(self):
return "volume is {}".format(self.volume)

b1 = Bubble(20)
b2 = Bubble(30)

print(b1)
45
Що тепер буде виведено на екран у результаті виконання програмного
коду?

9. Нехай до класу Bubble додано метод __add__()

class Bubble:
def __init__(self, volume):
self.volume = volume

def __str__(self):
return "volume is {}".format(self.volume)

def __add__(self, other):


volume = self.volume + other.volume
return Bubble(volume)

b1 = Bubble(20)
b2 = Bubble(30)
b3 = b1 + b2

print(b3)

Поясніть:
яку дію виконує метод __add__()?
чи відбулося перезавантаження методу __add__()?
що зберігається в змінній b3?
чи буде виведено повідомлення про помилку в результаті виконання
цього програмного коду?

46
Тема № 6. Абстракція та інкапсуляція
Мета: формування вмінь використання абстракції та інкапсуляції при
створенні програм.

План
1. Поняття абстракції.
a. абстрактні класи
b. абстрактні методи
c. абстрактні класи з імплементованими абстрактними методами
d. абстракція в Python
2. Поняття інкапсуляції.
3. Захищені (Protected) атрибути класу.
4. Закриті (Private) атрибути та методи класу.
5. Отримувачі (Getters, геттери) та установники (Setters, сеттери) в Python

Наслідування, поліморфізм, абстракція, інкапсуляція –


фундаментальні концепції ООП.

1. Поняття абстракції
a. Абстрактні класи
Абстрактний клас - це клас, який містить один або кілька абстрактних
методів.
Абстрактний метод - це метод, який, як правило, описується в
батьківському класі і не реалізується. Реалізація абстрактних методів
відбувається в підкласах (дочірніх класах).
У Python абстрактний клас є похідним із мета-класу ABC, який належить
модулю abc (Abstract Base Class). Тоді

from abc import ABC


class MyClass(ABC):

b. Абстрактні методи
Для визначення абстрактних методів в абстрактному класі необхідно
використати декоратор @abstractmethod. Цей декоратор необхідно
імпортувати з модуля abc:

from abc import ABC, abstractmethod

class MyClass(ABC):
@abstractmethod
def mymethod(self):
pass
47
Важливо:
 Абстрактний клас може містити як конкретні методи, так і абстрактні.
 Абстрактний клас працює як шаблон для інших класів.
Використовуючи абстрактний клас, можна визначити узагальнену
структуру, не забезпечуючи повної реалізації кожного методу. Методи,
що забезпечують загальну функціональність для всіх дочірніх класів,
визначаються як конкретні методи в абстрактному класі. Методи,
реалізація яких може відрізнятися, визначаються як абстрактні методи.
 Неможливо створити об’єкт абстрактного класу.
 Як правило, абстрактні методи, визначені в абстрактному класі, не
мають операторів тіла (містять pass). Але можна мати абстрактні
методи з реалізацією в абстрактному класі. Тоді будь-який підклас, що
походить від такого абстрактного класу, все таки повинен забезпечити
реалізацію таких абстрактних методів.
 Якщо якийсь абстрактний метод не реалізований дочірнім класом,
Python видає помилку.
Наприклад:

from abc import ABC, abstractmethod

class Parent(ABC):
#common functionality
def common(self):
print('In common method of Parent')
@abstractmethod
def vary(self):
pass

class Child1(Parent):
def vary(self):
print('In vary method of Child1')

class Child2(Parent):
def vary(self):
print('In vary method of Child2')

# object of Child1 class


obj = Child1()
obj.common()
obj.vary()
print('_________________')

48
# object of Child2 class
obj = Child2()
obj.common()
obj.vary()

Результати:

In common method of Parent


In vary method of Child1
_________________
In common method of Parent
In vary method of Child2

c. Абстрактні класи з імплементованими абстрактними


методами
Навіть якщо абстрактний метод реалізований в абстрактному класі, у
підкласі все одно необхідно описати абстрактний метод:

from abc import ABC, abstractmethod

class Parent(ABC):
#common functionality
def common(self):
print('In common method of Parent')
@abstractmethod
def vary(self):
print('In vary method of Parent')

class Child(Parent):
pass

# object of Child1 class


obj = Child()
obj.common()
obj.vary()

Результат:

Traceback (most recent call last):


File "D:\Python37-32\classes_objects\test.py", line 15,
in <module>
obj = Child()
TypeError: Can't instantiate abstract class Child with
abstract methods vary
49
Якщо реалізувати метод в дочірньому класі, то програма працюватиме
коректно:

from abc import ABC, abstractmethod

class Parent(ABC):
#common functionality
def common(self):
print('In common method of Parent')
@abstractmethod
def vary(self):
print('In vary method of Parent')

class Child(Parent):
def vary(self):
print('In vary method of Child')

# object of Child1 class


obj = Child()
obj.common()
obj.vary()

Результат:

In common method of Parent


In vary method of Child

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

Нехай є абстрактний клас Payment, який має абстрактний метод


payment(). Та є два дочірні класи CreditCardPayment і MobileWalletPayment,
які реалізують абстрактний спосіб метод payment() відповідно до їх
функціональних можливостей.
Як користувач, ми абстрагуємося від цієї реалізації, коли створюється
об'єкт CreditCardPayment і викликається метод payment() класу
50
CreditCardPayment, а також коли створюється об'єкт MobileWalletPayment і
викликається метод payment() класу MobileWalletPayment:

from abc import ABC, abstractmethod

class Payment(ABC):
def print_slip(self, amount):
print('Purchase of amount- ', amount)

def payment(self, amount):


pass

class CreditCardPayment(Payment):
def payment(self, amount):
print('Credit card payment of- ', amount)

class MobileWalletPayment(Payment):
def payment(self, amount):
print('Mobile wallet payment of- ', amount)

obj1 = CreditCardPayment()
obj1.payment(100)
obj1.print_slip(100)
print(isinstance(obj1, Payment))

print('________')

obj2 = MobileWalletPayment()
obj2.payment(200)
obj2.print_slip(200)
print(isinstance(obj2, Payment))

Результати:

Credit card payment of- 100


Purchase of amount- 100
True
________
Mobile wallet payment of- 200
Purchase of amount- 200
True

51
2. Поняття інкапсуляції
Інкапсуляція – обмеження прямого доступу до складових об’єкта
(атрибутів і методів). Інкапсуляція робить деякі з компонент доступними
тільки всередині класу.
Тобто інкапсуляція реалізує ідею упаковки атрибутів і методів деякого
об’єкта в один блок. Обмеження на прямий доступ до атрибутів і методів дає
можливість запобігти випадковій зміні даних.
Інкапсуляція в Python працює на рівні угоди між програмістами про те,
які атрибути і методи є загальнодоступними, а які – внутрішніми
(приватними).
Клас є прикладом інкапсуляції (рис. 1.10):

Рис. 1.10. Клас як засіб інкапсуляції

Приклад інкапсуляції: в компанії є відділи – розрахунків, фінансів,


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

2. Захищені (Protected) атрибути класу


Захищені елементи – це ті елементи класу, до яких не можна отримати
доступ поза межами класу, але до них можна звернутися зсередини класу та
його підкласів. Щоб зробити елемент захищеним необхідно поставити
підкреслення "_" перед його іменем:

class_basic_encapsulation_1.py

# Creating a base class


class Base:
def __init__(self):

# Protected member
self._a = 2

# Creating a derived class


class Derived(Base):
52
def __init__(self):

# Calling constructor of
# Base class
Base.__init__(self)
print("Calling protected member of base class: ")
print(self._a)

obj1 = Base()

# Calling protected member


# Outside class will result in
# AttributeError
print(obj1.a)

#obj2 = Derived()

3. Закриті (Private) атрибути та методи класу


Закриті елементи схожі на захищені, відмінність у тому, що до закритих
елементів класу не повинно бути доступу ні за межами класу, ні всередині
базового класу. Для визначення закритого (приватного) елемента перед його
іменем необхідно поставити подвійне підкреслення "__":

class_basic_encapsulation_2.py

# Creating a Base class


class Base:
def __init__(self):
self.a = "Practice makes perfect"
self.__c = "Practice__makes__perfect"

# Creating a derived class


class Derived(Base):
def __init__(self):

# Calling constructor of
# Base class
Base.__init__(self)
print("Calling private member of base class: ")
print(self.__c)
# Driver code
obj1 = Base()
print(obj1.a)

# Uncommenting print(obj1.c) will


53
# raise an AttributeError

# Uncommenting obj2 = Derived() will


# also raise an AtrributeError as
# private member of base class
# is called inside derived class

Закриті методи
Створимо клас Car, який має два методи: drive () та updateSoftware ().
Коли об’єкт буде створений, він викличе закритий (приватний) метод
__updateSoftware (). Цей метод не можна викликати для об’єкта
безпосередньо, лише з класу:

class_car_encapsulation_1.py

class Car:

def __init__(self):
self.__updateSoftware()

def drive(self):
print('driving')

def __updateSoftware(self):
print('updating software')

redcar = Car()
redcar.drive()
#redcar.__updateSoftware() not accesible from object.

Результати
updating software
driving

Інкапсуляція запобігає випадковому, але не навмисному доступу.


Приватні атрибути та методи насправді не приховані, вони
перейменовані додаванням _Car на початку свого імені. Метод насправді
можна викликати за допомогою redcar._Car__updateSoftware()

Закриті атрибути:

class_car_encapsulation_2.py

class Car:
54
__maxspeed = 0
__name = ""

def __init__(self):
self.__maxspeed = 200
self.__name = "Supercar"

def drive(self):
print('driving with maxspeed
{}'.format(self.__maxspeed))

redcar = Car()
redcar.drive()
redcar.__maxspeed = 10 # will not change variable
because its private
redcar.drive()

Результати
driving with maxspeed 200
driving with maxspeed 200

Для того, щоб вирішити завдання необхідно застосувати


Для того, щоб змінити значення приватної змінної, необхідно
використати метод установки (setter):

class_car_encapsulation_3.py

class Car:

__maxspeed = 0
__name = ""

def __init__(self):
self.__maxspeed = 200
self.__name = "Supercar"

def drive(self):
print('driving with maxspeed
{}'.format(self.__maxspeed))

def setMaxSpeed(self,speed):
self.__maxspeed = speed

55
redcar = Car()
redcar.drive()
redcar.setMaxSpeed(320)
redcar.drive()

Результати
driving with maxspeed 200
driving with maxspeed 320

Перед тим, як перейти до вивчення отримувачів (Getters, геттери) та


установників (Setters, сеттери), розглянемо приклад, що ілюструє
використання всіх трьох розглянутих модифікаторів доступу
(загальнодоступного, захищеного та приватного):

# program to illustrate access modifiers of a class

# Basic class
class Basic:

# public data member


var1 = None

# protected data member


_var2 = None

# private data member


__var3 = None

# constructor
def __init__(self, var1, var2, var3):
self.var1 = var1
self._var2 = var2
self.__var3 = var3

# public member function


def displayPublicMembers(self):

# accessing public data members


print("Public Data Member: ", self.var1)

# protected member function


def _displayProtectedMembers(self):

# accessing protected data members


print("Protected Data Member: ", self._var2)
56
# private member function
def __displayPrivateMembers(self):

# accessing private data members


print("Private Data Member: ", self.__var3)

# public member function


def accessPrivateMembers(self):

# accessing private memeber function


self.__displayPrivateMembers()

# derived class
class Derived(Basic):

# constructor
def __init__(self, var1, var2, var3):
Basic.__init__(self, var1, var2, var3)

# public member function


def accessProtectedMemebers(self):

# accessing protected member functions of


Basic class
self._displayProtectedMembers()

# creating objects of the derived class


obj = Derived("Practice", 32, "hours")

# calling public member functions of the class


obj.displayPublicMembers()
obj.accessProtectedMemebers()
obj.accessPrivateMembers()

# Object can access protected member


print("Object is accessing protected member:", obj._var2)

# object can not access private member, so it will


generate Attribute error
#print(obj.__var3)

5. Отримувачі (Getters, геттери) та установники (Setters, сеттери) в


Python

57
Отримувачі (Геттери) - це методи, які дають змогу отримати доступ до
приватних атрибутів із класу.
Установники (Сеттери) - це методи, які дають змогу встановити
значення приватних атрибутів у класі.

Крок 1. Використаємо нормальні методи для дослідження поведінки


геттерів і сеттерів.
Визначимо звичайні методи get() і set() без жодної спеціальної реалізації:

# Python program showing a use


# of get() and set() method in
# normal function

class Person:
def __init__(self, age = 0):
self._age = age

# getter method
def get_age(self):
return self._age

# setter method
def set_age(self, x):
self._age = x

ray = Person()

# setting the age using setter


ray.set_age(21)

# retrieving age using getter


print(ray.get_age())

print(ray._age)

Результати:

21
21

У наведеному коді get_age() та set_age() виступають як звичайні


функції, їх можна не розглядати як геттери та сетери. Для досягнення такої
функціональності необхідно використати спеціальну функцію property().

58
Крок 2. Використаємо функцію property() для управління
поведінкою геттерів та сеттерів.
У Python property() - це вбудована функція, яка визначає та повертає
нове значення властивості об'єкта, має три методи: getter(), setter() та
delete():

# Python program showing a


# use of property() function

class Person:
def __init__(self):
self._age = 0

# function to get value of _age


def get_age(self):
print("getter method called")
return self._age

# function to set value of _age


def set_age(self, a):
print("setter method called")
self._age = a

# function to delete _age attribute


def del_age(self):
del self._age

age = property(get_age, set_age, del_age)

mark = Person()

mark.age = 10

print(mark.age)

Результати:

setter method called


getter method called
10

У наведеному вище коді є лише один оператор print() в рядку # 25,


але виведення складається з трьох рядків завдяки методу setter set_age(), що
викликається в рядку # 23, і методу getter get_age (), що викликається в рядку

59
# 25. Отже, age - це властивість об’єкта, яка дає можливість захистити
доступ приватної змінної.

Крок 3. Є ще один спосіб реалізувати функцію property() –


використати декоратор. Використаємо декоратор @property для управління
поведінкою геттерів та сетерів.
Python @property - один із вбудованих декораторів. Основна мета будь-
якого декоратора - змінити методи або атрибути вашого класу таким чином,
щоб користувачеві вашого класу не потрібно було вносити зміни у свій код.

# Python program showing the use of


# @property

class Person:
def __init__(self):
self._age = 0

# using property decorator


# a getter function
@property
def age(self):
print("getter method called")
return self._age

# a setter function
@age.setter
def age(self, a):
if(a < 18):
raise ValueError("Sorry you age is below
eligibility criteria")
print("setter method called")
self._age = a

mark = Person()

mark.age = 19

print(mark.age)

Результати:

setter method called


getter method called
19

60
У наведеному вище коді рядок 15-16 діє як код перевірки, що викликає
ValueError, якщо користувач намагається ініціалізувати вік зі значенням
менше 18. Таким чином, будь-який тип перевірки може бути застосований до
функцій getter або setter.

Абстракція VS Інкапсуляція
Абстракція фокусується на роботі об’єкта, в той час як інкапсуляція
приховує особливості роботи класу.

Абстракція Інкапсуляція

Абстракція використовується для Інкапсуляція використовується для


вирішення проблем та питань, що вирішення проблем та питань, що
виникають на стадії проектування. виникають на етапі впровадження.

Абстракція фокусується на тому, що Інкапсуляція фокусується на


робить об’єкт, а не на тому, як приховуванні коду та даних в
реалізуються деталі. одному блоці, щоб захистити дані
від зовнішнього світу.

Абстракція реалізується за Інкапсуляція реалізується за


допомогою класу Abstract. допомогою модифікаторів доступу
(загальнодоступних, захищених та
приватних)

Її застосування відбувається на рівні Її застосування відбувається на рівні


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

Практичні завдання

Завдання 1. Створити класи Truck, Car та Bus, кожен з яких містить


методи start(), stop(), accelerate(). Класи Truck, Car та Bus є
дочірніми до абстрактного класу Automobile. Структура класів повинна
бути такою, як показано на схемі:

61
В абстрактному класі Automobile описати абстрактні методи
start(), stop(), accelerate(), але не реалізовувати їх. У
дочірніх класах імплементувати методи start(), stop(),
accelerate(). Створити по одному об’єкту кожного класу.
Застосувати до них розроблені методи.
Урахувати, що при створенні дочірніх класів, розробнику не потрібно
шукати методи для реалізації, їх можна бачити в абстрактному класі.
Переконатися, що якщо в одному із підкласів (Truck, Car, Bus) не
реалізувати один із методів, то Python автоматично видасть
повідомлення про помилку.

Завдання 2. Нехай задано програмний код:

class Robot:

def __init__(self, name, version, price):


self.name = name
self.version = version
self.price = price

def move(self, speed):


print("{} can move with speed {}
m".format(self.name, speed))

obj = Robot("Leju", "AL-PRO-E1E", 9570.0)


obj.move(100)

62
Зробити усі змінні в класі Robot приватними. Спробувати
надрукувати таку змінну за межами класу.
Змінити метод move() так, щоб використовувати приватну змінну і
викликати його з основної програми. (Пам’ятайте про необхідність створення
метода, який надає доступ до move() ззовні класу).
Створити метод setter() для однієї зі змінних. Використати створений
метод, щоб змінити значення змінної.
Створити метод getter() для тієї самої змінної, що і метод setter().
Використати метод getter() для доступу та виведення на екран цієї змінної.

Завдання 3. Для своєї предметної області у створених класи зробити деякі


змінні захищеними, а деякі приватними. Створити методи setter() та
getter() для таких змінних, використати їх в основній програмі.

Контрольні запитання
1. Назвіть суть абстракції в об’єктно-орієнтованому програмуванні.
2. Які класи і методи називаються абстрактними?
3. Як реалізується абстракція в мові програмування Python?
4. Нехай задано програмний код:

from abc import ABC, abstractmethod

class Animal(ABC):
@abstractmethod
def move(self):
pass

class Human(Animal):
def move(self):
print("I can walk and run")

class Snake(Animal):
def move(self):
print("I can crawl")

class Dog(Animal):
def move(self):
print("I can bark")

class Lion(Animal):
def move(self):
print("I can roar")
63
R = Human()
R.move()

K = Snake()
K.move()

R = Dog()
R.move()

K = Lion()
K.move()

 Як можна охарактеризувати клас Animal(ABC)?


 Якщо в клас Snake(Animal) описати так:

class Snake(Animal):
pass

то чи працюватиме програма?

5. Назвіть суть абстракції в об’єктно-орієнтованому програмуванні.


6. Які елементи класу називають захищеними (Protected)? Як вони
визначаються в програмі?
7. Які елементи класу називають закритими (Private)? Як вони визначаються
в програмі?
8. Для чого призначений програмний код:

def __displayPrivateMembers(self):
print("Private Data Member: ", self.__var3)

def accessPrivateMembers(self):
self.__displayPrivateMembers()

10. Для чого в Python використовуються отримувачі (Getters, геттери) та


установники (Setters, сеттери)?
11. Чим відрізняються поняття абстракції та інкапсуляції в об’єктно-
орієнтованому програмуванні?

64
Розділ ІІ. Графічний інтерфейс користувача
Тема №7. Віджети мітка, кнопка, текстове поле.
Мета: формування вмінь створення графічного інтерфейсу користувача з
використанням віджетів мітка, кнопка, текстове поле та технології Grid.

Теоретичні питання

План
1. Використання модуля tkinter для створення графічного інтерфейсу
користувача.
2. Віджети мітка, кнопка, текстове поле.
3. Менеджер розмітки grid.

1. Використання модуля tkinter для створення графічного інтерфейсу


користувача

У Python є багато варіантів розробки графічного інтерфейсу


користувача. Модуль tkinter – це стандартний інтерфейс Python для
інструментарію Tk GUI (Toolkit for graphical user interface), що постачається
разом із Python. Python with tkinter – це найшвидший і найпростіший спосіб
створення додатків GUI.

Приклад 1. Розглянемо два програмних коди розв’язання задачі


обчислення середньої швидкості автомобіля без та з використанням
графічного інтерфейсу користувача

Без використання GUI:

print('''
Автомобіль проїхав половину шляху зі швидкістю v1 км/год.
Половину часу, який залишився, він їхав зі швидкістю v2
км/год,
а останню ділянку – зі швидкістю v3 км/год.
Знайти середню швидкість автомобіля на всьому шляху.
'''
)

# уведення даних
v1 = float(input('Уведіть швидкість автомобіля v1 (у км/год)
-> '))

65
v2 = float(input('Уведіть швидкість автомобіля v2 (у км/год)
-> '))
v3 = float(input('Уведіть швидкість автомобіля v3 (у км/год)
-> '))

# обчислення середньої швидкості


v_average = (2*v1*(v2 + v3))/(2*v1 + v2 + v3)

# виведення результату
print('Середня швидкість автомобіля на всьому шляху = {:.2f}
км/год'.format(v_average)

Результат:

З використанням GUI:

from tkinter import *

window = Tk()
window.title("example_1")
window.geometry('550x400')

task = '''
Автомобіль проїхав половину шляху зі швидкістю v1 км/год.
Половину часу, який залишився, він їхав зі швидкістю v2
км/год,
а останню ділянку – зі швидкістю v3 км/год.
Знайти середню швидкість автомобіля на всьому шляху.
'''

lbl_task = Label(window, text=task, font=("Arial Bold",


10),justify=LEFT)
66
lbl_v1 = Label(window, text="v1 =", font=("Arial Bold",
18))
lbl_v2 = Label(window, text="v2 =", font=("Arial Bold",
18))
lbl_v3 = Label(window, text="v3 =", font=("Arial Bold",
18))

lbl_task.grid(row=0, column=0, columnspan=4)


lbl_v1.grid(row=1, column=0)
lbl_v2.grid(row=2, column=0)
lbl_v3.grid(row=3, column=0)

txt_v1 = Entry(window, font=("Arial", 12))


txt_v2 = Entry(window, font=("Arial", 12))
txt_v3 = Entry(window, font=("Arial", 12))

txt_v1.grid(row=1, column=1, sticky=W, ipady=8)


txt_v2.grid(row=2, column=1, sticky=W, ipady=8)
txt_v3.grid(row=3, column=1, sticky=W, ipady=8)

def culc_average_speed():
v1 = float(txt_v1.get())
v2 = float(txt_v2.get())
v3 = float(txt_v3.get())

v_average = (2*v1*(v2 + v3))/(2*v1 + v2 + v3)


str_v_average = "{:5.2f}".format(v_average)

lbl_v_average = Label(window,text= "Середня швидкість


=", font=("Arial Bold", 16))
lbl_result = Label(window,text= str_v_average,
font=("Arial Bold", 16))
lbl_unit = Label(window,text= "км/год", font=("Arial
Bold", 16))

lbl_v_average.grid(row=5, column=0)
lbl_result.grid(row=5, column=1)
lbl_unit.grid(row=5, column=2, sticky=W)

def close_window():
window.destroy()

btn = Button(window, text="Обчислити", font=("Arial


Bold", 16), command=culc_average_speed)
67
btn.grid(row=4, column=0, pady=14)

btn = Button(window, text="Вийти", font=("Arial Bold",


16), command=close_window)
btn.grid(row=4, column=4, pady=14)

window.mainloop()

Результат:

Приклад 2. Розглянемо два програмних коди розв’язання задачі


побудови таблиці залежності переміщення тіла від часу без та з
використанням графічного інтерфейсу користувача.

Без використання GUI:

print('''
Тіло масою 5 кг рухається горизонтально з початковою
швидкістю 1 м/с під дією сили 30 Н,
що напрямлена під кутом 60 градусів до горизонту.
Запишіть рівняння залежності переміщення від часу, якщо
коефіцієнт тертя становить 0,1.
'''
)

from math import sin, cos, radians


68
# уведення даних

m = float(input('Уведіть масу тіла в кг -> '))


v0 = float(input('Уведіть початкову швидкість у м/с -> '))
F = float(input('Уведіть значення сили в Н -> '))
alpha = float(input('Уведіть кут, під яким напрямлена сила,
в градусах -> '))
miu = float(input('Уведіть значення коефіцієнту тертя -> '))

# ініціалізація прискорення вільного падіння

g = 9.8

# переведення градусів у радіани


alpha_radians = radians(alpha)

# обчислення прискорення та виведення значення прискорення

a = (F*cos(alpha_radians) - miu*(m*g -
F*sin(alpha_radians))) / m
print('\nПрискорення a = {:.1f} м/c{}\n'.format(a,chr(178)))

# виведення таблиці

print('Таблиця залежності переміщення від часу (перші 10


секунд):')
print('{:7} | {:6}'.format('t (сек)','x (м)'))
print('-'*20)
for t in range(11):
x = v0*t + (a*t**2)/2
print('{:7d} | {:6.1f}'.format(t,x))

Результат:

69
З використанням GUI:

from tkinter import *


from math import sin, cos, radians

window = Tk()
window.title("example_1")
window.geometry('800x800')

task = '''
Тіло масою 5 кг рухається горизонтально з початковою
швидкістю 1 м/с
під дією сили 30 Н, що напрямлена під кутом 60 градусів
до горизонту.
Запишіть рівняння залежності переміщення від часу, якщо
коефіцієнт тертя становить 0,1.
'''

lbl_task = Label(window, text=task, font=("Arial Bold",


12),justify=LEFT)
70
lbl_header1 = Label(window, text="Вхідні дані",
font=("Arial Bold", 16))

lbl_m = Label(window, text="m =", font=("Arial Bold",


16))
lbl_v0 = Label(window, text="vo =", font=("Arial Bold",
16))
lbl_F = Label(window, text="F =", font=("Arial Bold",
16))
lbl_alpha = Label(window, text=chr(945)+" =",
font=("Arial Bold", 16))
lbl_miu = Label(window, text=chr(956)+" =", font=("Arial
Bold", 16))

lbl_task.grid(row=0, column=0, columnspan=4)


lbl_header1.grid(row=1, column=0, columnspan=2)

lbl_m.grid(row=2, column=0)
lbl_v0.grid(row=3, column=0)
lbl_F.grid(row=4, column=0)
lbl_alpha.grid(row=5, column=0)
lbl_miu.grid(row=6, column=0)

txt_m = Entry(window, font=("Arial", 12))


txt_v0 = Entry(window, font=("Arial", 12))
txt_F = Entry(window, font=("Arial", 12))
txt_alpha = Entry(window, font=("Arial", 12))
txt_miu = Entry(window, font=("Arial", 12))

txt_m.grid(row=2, column=1, sticky=W, ipady=8)


txt_v0.grid(row=3, column=1, sticky=W, ipady=8)
txt_F.grid(row=4, column=1, sticky=W, ipady=8)
txt_alpha.grid(row=5, column=1, sticky=W, ipady=8)
txt_miu.grid(row=6, column=1, sticky=W, ipady=8)

def create_a_table():
m = float(txt_m.get())
v0 = float(txt_v0.get())
F = float(txt_F.get())
alpha = float(txt_alpha.get())
miu = float(txt_miu.get())

g = 9.8
alpha_radians = radians(alpha)
71
a = (F*cos(alpha_radians) - miu*(m*g -
F*sin(alpha_radians))) / m

lbl_header2 = Label(window, text="Таблиця


залежності", font=("Arial Bold", 16))
lbl_header2.grid(row=1, column=3, columnspan=2)

for t in range(11):
x = v0*t + (a*t**2)/2
str_result = "{:3d} | {:6.1f}".format(t,x)
lbl_result = Label(window,text= str_result,
font=("Arial Bold", 16))
lbl_result.grid(row=t+2, column=3)

def close_window():
window.destroy()

btn = Button(window, text="Побудувати таблицю",


font=("Arial Bold", 16), command=create_a_table)
btn.grid(row=13, column=0, pady=14)

btn = Button(window, text="Вийти", font=("Arial Bold",


16), command=close_window)
btn.grid(row=15, column=0, pady=14)

window.mainloop()

Результат:

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

Щоб створити додаток з використанням tkinter необхідно:


1. Імпортувати модуль tkinter.
2. Створити головне вікно.
3. Додати віджети до головного вікна.
4. Застосувати обробник подій у віджетах.

Два основні методи при створенні Python-програми з GUI:


1. Tk(screenName = None, baseName = None, className =
'Tk', useTk = 1):
щоб створити головне вікно.
Основний код, який використовується для створення головного вікна
програми:
tk = tkinter.Tk(), де tk - ім'я об'єкта головного вікна

73
2. mainloop():
спрацьовує, коли програма готова до запуску.
mainloop() - це нескінченний цикл, який використовується для
запуску додатку, обробляє подію допоки, поки вікно не закриється.

Загальна структура програми:

from tkinter import *


tk = Tk()
tk.title('window title')

'''
widgets are added here
'''
mainloop()

Список Tkinter GUI віджетів:


1. Tkinter Label Widget
2. Tkinter Entry Widget
3. Tkinter Button Widget
4. Tkinter Check Button Widget
5. Tkinter RadioButton Widget
6. Tkinter ListBox Widget
7. Tkinter Scrollbar Widget
8. Tkinter Combobox Widget
9. Tkinter Scale Widget

2. Віджети мітка, кнопка, текстове поле


Мітка (Label) – це віджет, який відображає текст або зображення, які
користувачі переглядають, але не взаємодіють з ними.
Створення міток:

from tkinter import *


tk = Tk()
tk.title('Label Testing')
canvas = Canvas(tk, width=400, height=300, bg='snow')
canvas.pack()

label = Label(tk, text="Hello, Tkinter")


74
label.pack()
canvas.create_window(200, 25, window=label)

mainloop()

Результат:

Додамо стилів для мітки:

label = Label(tk,
text = "Hello, Tkinter",
bg = "Gainsboro",
fg = "Brown",
font=('helvetica', 24, 'bold'),
relief="ridge",
pady=15, padx=15)
canvas.create_window(200, 75, window=label)

mainloop()

Результат:

75
Кнопка (Button) – це віджет, призначений для взаємодії. Користувач
натискає кнопку, щоб виконати дію.
Створення кнопок:

from tkinter import *


tk = Tk()
tk.title('Button Testing')
canvas = Canvas(tk, width=400, height=300, bg='snow')
canvas.pack()

button1 = Button(tk,
text = "Quit!",
bg = "GhostWhite",
fg = "red",
font=('calibri', 14, 'bold', 'underline'),
relief="ridge",
pady=15, padx=15,
command = tk.destroy)
canvas.create_window(200, 75, window=button1)

button2 = Button(tk,
text = "Click me!",
bg = "GhostWhite",
fg = "green",
font=('calibri', 14, 'bold'),
relief="ridge",
pady=15, padx=15,
command = None)
canvas.create_window(200, 175, window=button2)
76
mainloop()

Результат:

Текстове поле (Entry) – це віджет, який відображає однорядкове


текстове поле для введення даних від користувача.
Створення текстових полів:

from tkinter import *


tk = Tk()
tk.title('Entry Testing')
canvas = Canvas(tk, width=400, height=300, bg='snow')
canvas.pack()

entry = Entry(tk,
bg = "blue",
fg = "yellow",
width = 50,
font = ('calibre',10,'normal'))
canvas.create_window(200, 75, window=entry)

mainloop()

Результат:

77
Однак цікавим для віджетів Entry є не те, як їх стилізувати. Важливо, як
їх використовувати. Є три основні операції, які можна виконати за
допомогою віджетів Entry:
1. Отримання тексту за допомогою .get()
2. Видалення тексту за допомогою .delete()
3. Вставка тексту за допомогою .insert()

>>> name = entry.get()


>>> name

>>> entry.delete(0)
>>> entry.delete(0, 4)
>>> entry.delete(0, tk.END)

>>> entry.insert(0, "Python")

Завдання. Створити програму Calculate the square root з інтерфейсом


як показано на рисунку:

78
Крок 1. Створення полотна
Canvas - це полотно, на якому можна розміщувати віджети:

tk.title('Square root')
canvas = Canvas(tk, width=400, height=300, bg='light
cyan')
canvas.pack()

Крок 2. Створення текстового поля для введення даних


Для отримання даних користувача можна використовувати поле для
введення. Можна вказати позицію, де поле для введення буде розміщене на
Canvas (у прикладі позиція встановлена на 200, 140):

txt = Entry(tk)
canvas.create_window(200, 140, window=txt)

Крок 3. Включення функції


Функція get_square_root() використовується для обчислення
квадратного кореня числа, яке було введено у текстовому полі. Результат
відображається в елементі мітка:

def get_square_root():
x = txt.get()
y = float(x)**0.5
str_y = '{:.2f}'.format(y)

lbl = Label(tk, text= str_y)


canvas.create_window(200, 230, window=lbl)

Крок 4. Додавання кнопки

79
Кнопка використовується для виконання функції get_square_root():

btn = Button(text='Get the Square Root',


command=get_square_root)
canvas.create_window(200, 180, window=btn)

Крок 5. Запуск повного коду програми

Додавання стилю до полотна та його елементів


Можна змінювати шрифти, кольори та інше:

canvas = Canvas(tk, width=400, height=300, bg='light


cyan')
canvas.pack()

lbl1 = Label(tk, text='Calculate the Square Root',


font=('helvetica',
14))
canvas.create_window(200, 25, window=lbl1)

lbl2 = Label(tk, text='Type your Number:',


font=('helvetica', 10))
canvas.create_window(200, 100, window=lbl2)

txt = Entry(tk)
canvas.create_window(200, 140, window=txt)

Мітка всередині функції:

lbl = Label(tk, text= str_y, font=('helvetica', 10,


'bold'))

Кнопка:

btn = Button(text='Get the Square Root',


command=get_square_root,
bg='brown', fg='white', font=('helvetica',
9, 'bold'))

3. Менеджер розмітки grid


У Tkinter є три вбудованих менеджера розмітки: pack, grid і place.
Place розміщує віджети, використовуючи абсолютне позиціонування.
Pack розміщує віджети по горизонталі і вертикалі.
Grid розміщує віджети в двомірної сітці.
80
Менеджер геометрії grid розміщує віджети у двовимірній таблиці.
Головний віджет розділений на рядки та стовпці, кожна клітинка в отриманій
таблиці може містити віджет (рис. 2.1):

Рис. 2.1. Схеми використання технології grid

Параметри grid:
row, column - значення рядка та стовпця для розташування віджета.
Обидва починаються з 0.
columnsnpan, rowspan – об’єднання стовпців, рядків. Віджет
займатиме декілька стовпців, рядків.
padx, pady - кількість пікселів навколо віджета для створення
зовнішніх відступів.
ipadx, ipady - створення внутрішніх відступів.
sticky - вказати значення s, n, e, w або їх комбінацію, наприклад nw, ne,
sw або se. Параметр указує, до якого боку клітинки віджет буде
прикріплений. Якщо ви використовуєте 'w' + 'e' + 'n' + 's', то віджет
заповнить клітинку. За замовчуванням – він розташовується у центрі
клітинки.

Приклад 3. Створити полотно з віджетами: мітка, текстове поле,


кнопка. Використати розмітку grid.

from tkinter import*

master=Tk()
81
master.title("Grid Widget")

label=Label(master, text="First Name",font=10)


label.grid(row=0)
entry = Entry(master)
entry.grid(row=0, column=1)

label=Label(master, text="Last Name", font=10)


label.grid(row=1)
entry = Entry(master)
entry.grid(row=1, column=1)

button1=Button(master, text="Submit")
button1.grid(row=2, column=1)

mainloop()

Результат:

Для зміни загального вигляду вікна додати:

master.geometry("250x100")
master.config(bg="lightgrey")

Приклад 3. З використанням технології grid розмістити кнопки на


полотні так, як показано на малюнку:

from tkinter import*


master=Tk()
master.grid()

82
button1=Button(master,text="B1")
button1.grid(row=1,column=0)

button2=Button(master, text="B2")
button2.grid(row=1,column=2)

button3=Button(master,text="B3")
button3.grid(row=0,column=1)

button4=Button(master,text="B4")
button4.grid(row=2,column=1)

mainloop()

Приклад 4. З використанням технології grid розмістити кнопки на


полотні так, як показано на малюнку:

from tkinter import*


master=Tk()
master.grid()

button1=Button(master,text="B1")
button1.grid(row=1,column=0)

button2=Button(master, text="B2")
button2.grid(row=1,column=2)

button3=Button(master,text="B3")
button3.grid(row=0,column=1)

button4=Button(master,text="B4")
button4.grid(row=2,column=1)

mainloop()

Приклад 5. З використанням технології grid розмістити кнопки на


полотні так, як показано на малюнку:
83
from tkinter import*
master=Tk()

button1=Button(master,text="B1")
button1.grid(row=1,column=1)

button2=Button(master, text="B2")
button2.grid(row=1,column=2)

button3=Button(master,text="B3")
button3.grid(row=1,column=3)

button4=Button(master,text="B4")
button4.grid(row=1,column=4)

button5=Button(master,text="B5")
button5.grid(row=1,column=5)

mainloop()

Приклад 6. З використанням технології grid розмістити віджети на


полотні так, як показано на малюнку:

from tkinter import*

master=Tk()
master.title("Grid Widget")
84
master.config(bg="lightgrey")

header = Label(master, text="Register Form",font=12)


header.grid(row = 0, column = 0,
columnspan = 3, padx = 5, pady = 5)

l1=Label(master, text="First Name", font=10)


l1.grid(row = 1, column = 0, sticky = W, pady = 2, padx = 2)
e1 = Entry(master, font=10)#, width=15)
e1.grid(row = 1, column = 1, pady = 2, padx = 2, ipady=4)

l2=Label(master, text="Last Name", font=10)


l2.grid(row = 2, column = 0, sticky = W, pady = 2, padx = 2)
e2 = Entry(master, font=10)
e2.grid(row = 2, column = 1, pady = 2, padx = 2, ipady=4)

# adding image (remember image should be PNG and not JPG)


img = PhotoImage(file = "images/red_nose.png")
img1 = img.subsample(2, 2)

# setting image with the help of label


l3 = Label(master, image = img1).grid(row = 1, column = 2,
columnspan = 2, rowspan = 2, padx = 5, pady = 5)

b1=Button(master, text="Submit", font=10)


b1.grid(row=3, column=1, pady = 5)

mainloop()

Як видно з прикладу, на формі можна розміщати малюнки у


форматі .png.

Практичні завдання

Завдання 1. Вибрати дві довільні задачі із списку наведеного нижче.


Створити програми для їх розв’язання з використанням GUI. Віджети
розмістити на полотні з використанням технології Grid. Додати малюнок.

 Дано висоту та радіус основи конуса, обчислити його об’єм.


 Дано повну поверхню та радіус основи циліндра, обчислити його
висоту.
85
 Дано сторони ромба та кут між сторонами, знайти його площу.
 Дано сторони та висоту трапеції, знайти її площу.
 Дано висоту та сторону правильної чотирикутної піраміди, обчислити її
об’єм.
 Дано висоту та сторону правильної трикутної призми, знайти її повну
поверхню.
 Дано площу основи та висоту циліндра, знайти його повну поверхню.
 Визначити, чи є неспадною послідовність цілих чисел x, y, z.
 Для входу до деякого комп’ютерного середовища необхідно ввести
пароль. Розробити програму, в якій за введеним паролем визначається,
чи має користувач доступ до комп’ютерного середовища.
 Час роботи працівника понад 40 годин на тиждень є понаднормовим та
оплачується в 1,5 рази від звичайної норми. Відомі час роботи
працівника за тиждень і регулярна погодинна оплата. Розробити
програму, що розраховує загальну оплату за тиждень, взявши до уваги
понаднормову роботу.
 Дано початкові та кінцеві показники спожитої електроенергії. Вартість
1кВт·год електроенергії становить 0,9грн, якщо обсяг споживання не
перевищив 100 кВт·год. Для понаднормових витрат тариф становить
1,68 грн. Обчисліть кількість спожитої електроенергії за та поза
нормою, суму до сплати. 
 Написати програму, в якій при введенні значення температури води
виводиться назва її стану.
 Написати програму, в якій при введенні назви місяця виводиться
кількість днів у місяці.
 Написати програму, в якій при введенні пори року виводяться назви
місяців, які належать до цієї пори.
 Дано список дисциплін та номер семестру, коли вони вивчаються.
Написати програму, в якій при введенні номера семестру (не менше 4
семестрів) виводиться список дисциплін, що вивчаються.
 Дано перелік континентів. Написати програму, в якій при введенні
назви континенту виводиться список країн (2-5 назв), що розташовані
на цьому континенті.
 Написати програму, в якій при введенні часу доби виводиться
відповідне привітання.

Контрольні запитання
1. Для чого призначений інструментарій Tk GUI. Як його підключити до
Python-програми?

86
2. Чим характеризується віджет Мітка? До якого класу модуля tkinter він
належить?
3. Чим характеризується віджет Кнопка? До якого класу модуля tkinter він
належить?
4. Чим характеризується віджет Текстове поле? До якого класу модуля
tkinter він належить?
5. Які вбудовані менеджери розмітки є в модулі tkinter. Назвіть
особливості використання менеджера grid.
6. Нехай задано програмний код:

from tkinter import *

def change():
b1['text'] = "Обчислити"
b1['bg'] = '#000000'
b1['fg'] = '#ffffff'

root = Tk()
b1 = Button(text="Обчислити",
width=15, height=3)
b1.config(command=change)
b1.pack()
root.mainloop()

Для чого призначена функція def change()?


7. Як працюватиме програма, якщо замінити код функції def change() на:

b1['text'] = "Обчислити"
b1[' activebackground '] = '#000000'
b1['activeforeground'] = '#ffffff'

87
Тема №8. Віджети перемикачі та прапорці
Мета: формування вмінь створення графічного інтерфейсу користувача з
використанням віджетів Checkbutton, Radiobutton.
Теоретичні питання

План
1. Віджет прапорці.
2. Віджет перемикачі

1. Віджет прапорці

Віджет Checkbutton (прапорці) використовується для відображення ряду


параметрів як прапорців. Користувач може вибрати кілька варіантів
одночасно:

from tkinter import *


tk = Tk()
tk.title('Checkbutton_1')
tk.geometry("250x100")

var1 = IntVar()
Checkbutton(tk, text='First', variable=var1).grid(row=0,
sticky=W)
var2 = IntVar()
Checkbutton(tk, text='Second', variable=var2).grid(row=1,
sticky=W)

mainloop()

Результат:

Відмітною рисою Checkbutton є можливість прив’язки до компонента


IntVar через параметр variable. Якщо прапорець встановлено, то IntVar
= 1; якщо прапорець не встановлено, то IntVar = 0. Тобто через IntVar
88
можна отримувати значення, встановлене користувачем, що впливає на хід
виконання програми.

Можна використати розширення ttk модуля tkinter для створення


програм графічного інтерфейсу з ефектами сучасної графіки, яких
неможливо досягти за допомогою лише tkinter:

# importing tkinter and ttk


from tkinter import *
from tkinter import ttk

# root
root = Tk()
root.geometry("250x150")

# This will depict the features of Simple Checkbutton


l = ttk.Label(root, text ='Simple
Checkbutton').grid(row=0, column=0)
chkbtn1 = Checkbutton(root, text
='Checkbutton1').grid(row=1, column=0)
chkbtn2 = Checkbutton(root, text
='Checkbutton2').grid(row=2, column=0)

# This will depict the features of ttk.Checkbutton


Label(root, text ='ttk.Checkbutton').grid(row=0,
column=1)
chkbtn1 = ttk.Checkbutton(root, text
='Checkbutton1').grid(row=1, column=1)
chkbtn2 = ttk.Checkbutton(root, text
='Checkbutton2').grid(row=2, column=1)

root.mainloop()

Результат:

89
Приклад 1. Створити програму, в результаті роботи якої користувачеві
надається можливість серед запропонованих обрати улюблений колір
(кольори). Вивести на екран назву кольору та 1, якщо користувач обрав цей
колір, 0 в протилежному випадку.

from tkinter import *

tk = Tk()
tk.title("Check the color")
tk.geometry("210x180")

def display_checked():
'''check if the checkbuttons have been toggled, and
display
a value of '1' if they are checked, '0' if not
checked'''
red = red_var.get()
yellow = yellow_var.get()
green = green_var.get()
blue = blue_var.get()

print("red: {}\nyellow:{}\ngreen: {}\nblue:


{}".format(
red, yellow, green, blue))

# Create label
lbl = Label(tk, text="Which colors do you like below?")
lbl.grid(row=0)

# Create variables and checkbuttons


red_var = IntVar()
Checkbutton(tk, width=10, text="red", variable=red_var,
bg="red").grid(row=1, sticky=W)
yellow_var = IntVar()
Checkbutton(tk, width=10, text="yellow",
variable=yellow_var, bg="yellow").grid(row=2, sticky=W)
green_var = IntVar()
Checkbutton(tk, width=10, text="green",
variable=green_var, bg="green").grid(row=3, sticky=W)
blue_var = IntVar()
Checkbutton(tk, width=10, text="blue", variable=blue_var,
bg="blue").grid(row=4, sticky=W)

# Create Buttons, one to check which colors are checked,


# and another to close the window.
90
Button(tk, text="Check it",
command=display_checked).grid(row=5)
Button(tk, text="Qiut", command=tk. destroy).grid(row=6)

tk.mainloop()

Результат:

red: 1
yellow:0
green: 1
blue: 1

Приклад 2. Створити програму, в результаті роботи якої користувачеві


надається можливість перемикати кнопку. Якщо кнопку ввімкнено
з’являється повідомлення ON та квадрат зеленого кольору. Якщо кнопку
вимкнено з’являється повідомлення OFF та квадрат червоного кольору.

from tkinter import *


ws = Tk()
ws.title('PythonGuide')
ws.geometry('200x100')

def switchState():
if cb1.get() == 1:
disp_Lb.config(text='ON')

elif cb1.get() == 0:
disp_Lb.config(text='OFF')
else:
disp_Lb.config(text='error!')

switch_on = PhotoImage(width=50, height=50)


91
switch_off = PhotoImage(width=50, height=50)

switch_on.put(("green",), to=(0, 0, 23,23))


switch_off.put(("red",), to=(24, 0, 47, 23))
cb1 = IntVar()
Checkbutton(ws, image=switch_off, selectimage=switch_on,
onvalue=1, offvalue=0, variable=cb1,
indicatoron=False,
command=switchState).pack(padx=20, pady=10)

disp_Lb = Label(ws)
disp_Lb.pack()
ws.mainloop()

Результат:

Приклад 3. Створити програму, в результаті роботи якої користувачеві


надається можливість перемикати кнопку. Якщо кнопку ввімкнено
з’являється повідомлення ON та квадрат зеленого кольору. Якщо кнопку
вимкнено з’являється повідомлення OFF та квадрат червоного кольору.

from tkinter import *


ws = Tk()
ws.title('PythonGuide')
ws.geometry('200x100')

def switchState():
if cb1.get() == 1:
disp_Lb.config(text='ON')

elif cb1.get() == 0:
disp_Lb.config(text='OFF')
else:
disp_Lb.config(text='error!')

switch_on = PhotoImage(width=50, height=50)


switch_off = PhotoImage(width=50, height=50)

92
switch_on.put(("green",), to=(0, 0, 23,23))
switch_off.put(("red",), to=(24, 0, 47, 23))
cb1 = IntVar()
Checkbutton(ws, image=switch_off, selectimage=switch_on,
onvalue=1, offvalue=0, variable=cb1,
indicatoron=False,
command=switchState).pack(padx=20, pady=10)

disp_Lb = Label(ws)
disp_Lb.pack()
ws.mainloop()

Результат:

Приклад 4. Створити програму, в результаті роботи якої користувачеві


надається можливість зробити вибір між такими опціями: music, video, photo.
Після здійснення вибору з використанням інформаційного вікна виводиться
повідомлення, наприклад, «you select music» так, як показано на малюнку:

from tkinter import *


import tkinter.messagebox
a= Tk()
93
a.geometry("400x400")

def music():
tkinter.messagebox.showinfo(title="music",message="you
select music")
def video():
tkinter.messagebox.showinfo(title="video",message="you
select video")
def photo():
tkinter.messagebox.showinfo(title="photo",message="you
select photo")

CheckVar1 = IntVar()
CheckVar2 = IntVar()
CheckVar3 = IntVar()

C1 = Checkbutton(a, text = "Music",fg="red", bg="green",


font="Castellar",height=5,width=5, relief="solid",
variable = CheckVar1, onvalue = 1, offvalue = 0,
command = music).pack()

Label(a, text="").pack()#space

C2 = Checkbutton(a, text = "Video",fg="red", bg="green",


font="Castellar",height=5,width=5, relief="solid",
variable = CheckVar2,onvalue = 1, offvalue = 0,
command = video).pack()

Label(a, text="").pack()#space

C3 = Checkbutton(a, text = "Photo",fg="red", bg="green",


font="Castellar",height=5,width=5, relief="solid",
variable = CheckVar3, onvalue = 1, offvalue = 0,
command = photo).pack()

a.mainloop()

2. Віджет перемикачі

Віджет Radiobutton (перемикачі) використовується для відображення


ряду параметрів як перемикачів. Користувач може одночасно вибрати лише
один параметр:

from tkinter import *


94
tk = Tk()
tk.title('Radiobutton_1')
tk.geometry("250x100")

var = IntVar()
Radiobutton(tk, text='First', variable=var,
value=1).grid(row=0, sticky=W)
Radiobutton(tk, text='Second', variable=var,
value=2).grid(row=1, sticky=W)

mainloop()

Результат:

Відмітною рисою Radiobutton є те, що в усіх кнопок однієї групи


властивість variable має одне й те саме значення – значення, пов’язане зі
змінною var. А властивості value надаються різні значення цієї змінної.
Щоб відобразити індикатор вікна кнопок слід встановити var.set(0)

Можна використати розширення ttk модуля tkinter для створення


програм графічного інтерфейсу з ефектами сучасної графіки, яких
неможливо досягти за допомогою лише tkinter:

# importing tkinter and ttk


from tkinter import *
from tkinter import ttk

# root
root = Tk()
root.geometry("250x150")

# This will depict the features of Simple Radiobutton


var1 = IntVar()
Label(root, text ='Simple Radiobutton').grid(row=0,
column=0)

95
rdbtn1 = Radiobutton(root, text ='Radiobutton1',
variable=var1, value=1).grid(row=1, column=0)
rdbtn2 = Radiobutton(root, text ='Radiobutton2',
variable=var1, value=2).grid(row=2, column=0)

# This will depict the features of ttk.Radiobutton


var2 = IntVar()
Label(root, text ='ttk.Radiobutton').grid(row=0,
column=1)
rdbtn1 = ttk.Radiobutton(root, text ='Radiobutton1',
variable=var2, value=3).grid(row=1, column=1)
rdbtn2 = ttk.Radiobutton(root, text ='Radiobutton2',
variable=var2, value=4).grid(row=2, column=1)

root.mainloop()

Результат:

Можливий такий підхід до створення перемикачів:

# Importing Tkinter module


from tkinter import *
#from tkinter.ttk import *

# Creating master Tkinter window


master = Tk()
master.geometry("175x175")

# Tkinter string variable


# able to store any string value
v = StringVar(master, "2")

# Dictionary to create multiple buttons


values = {"RadioButton 1" : "1",
96
"RadioButton 2" : "2",
"RadioButton 3" : "3",
"RadioButton 4" : "4",
"RadioButton 5" : "5"}

# Loop is used to create multiple Radiobuttons


# rather than creating each button separately
for (text, value) in values.items():
Radiobutton(master, text = text, variable = v,
value = value, indicator = 0,
background = "light blue").pack(fill = X,
ipady = 5)

# Infinite loop can be terminated by


# keyboard or mouse interrupt
# or by any predefined function (destroy())
mainloop()

Результат:

Приклад 5. Створити програму, в результаті роботи якої користувачеві


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

from tkinter import *

tk = Tk()
tk.title("Change the color")
tk.geometry("210x320")

def change_color():

97
if var.get() == 1:
lbl2['bg'] = 'red'
elif var.get() == 2:
lbl2['bg'] = 'green'
elif var.get() == 3:
lbl2['bg'] = 'blue'

lbl1 = Label(tk, text="Which color of the lable do you


choose?")
lbl1.grid(row=0)

var = IntVar()
var.set(0)
red = Radiobutton(tk, text="red", variable=var,
value=1).grid(row=1, sticky=W)
green = Radiobutton(tk, text="green", variable=var,
value=2).grid(row=2, sticky=W)
blue = Radiobutton(tk, text="blue", variable=var,
value=3).grid(row=3, sticky=W)

Button(tk, text="Change",
command=change_color).grid(row=5)

lbl2 = Label(tk, text="Change this color", width=20,


height=10, bg='light grey')
lbl2.grid(row=6)

tk.mainloop()

Результат:

98
Практичні завдання

Завдання 1. Створити програму, в результаті роботи якої користувачеві


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

Завдання 2. Створити програму, в результаті роботи якої користувачеві


надається можливість вибрати одну або декілька опцій із запропонованих.
Після здійснення вибору на полотні відбувається зміна. Наприклад:
 змінюється атрибут text мітки;
 змінюється колір фону або тексту мітки;
 з’являється / зникає рамка навколо мітки;
 з’являється / зникає мітка (мітка може бути представлена у
вигляді картинки);
 інше.

Один із можливих підходів до розв’язання завдання представлено


на рисунку:

99
Завдання 3. Створити програму, в результаті роботи якої користувачеві
надається можливість обирати серед запропонованих імен та відповідно
до імені виводити номер телефона. Один із можливих підходів до
розв’язання завдання представлено на рисунку:

Завдання 4. Створити програму, в результаті роботи якої користувачеві


надається можливість вибрати одну опцію із запропонованих. Після
здійснення вибору на полотні відбувається зміна. Наприклад:
 змінюється атрибут text мітки;
 змінюється колір фону або тексту мітки;
 з’являється / зникає рамка навколо мітки;

100
 з’являється / зникає мітка (мітка може бути представлена у
вигляді картинки);
 з’являється інформаційне вікно;
 інше.

Один із можливих підходів до розв’язання завдання представлено


на рисунку:

Контрольні запитання
1. Для чого призначений інструментарій Tk GUI. Як його підключити до
Python-програми?
2. Чим характеризується віджет Прапорці? До якого класу модуля tkinter
він належить?
3. Якщо прапорець встановлено, то якого значення набуває змінна, пов’язана
з параметром variable?
4. Які вбудовані менеджери розмітки є в модулі tkinter. Назвіть
особливості використання менеджера grid.
5. Для чого призначений інструментарій Tk GUI. Як його підключити до
Python-програми?
6. Чим характеризується віджет Перемикачі? До якого класу модуля
tkinter він належить?
7. Чи може властивість variable усіх кнопок однієї групи перемикачів мати
різні значення?
8. Який оператор треба використати, щоб відобразити індикатор вікна
кнопок?
9. Які вбудовані менеджери розмітки є в модулі tkinter. Назвіть
особливості використання менеджера grid.
10.Яка функція обрана у наступному коді?
101
from tkinter import *
root = Tk ()
var1 = IntVar ()
var2 = IntVar ()
ch1 = Checkbutton (root, text = 'sin(x) ', variable =
var1,
onvalue = 1, offvalue = 0)
ch2 = Checkbutton (root, text = 'cos(x)', variable = var2,

onvalue = 0, offvalue = 1)
ch1.pack ()
ch2.pack ()
root.mainloop ()

Тема №9. Віджети список, прокрутка та поле зі списком


Мета: формування вмінь створення графічного інтерфейсу користувача з
використанням віджета Radiobutton.
Теоретичні питання

План
1. Віджет список.
2. Віджет прокрутка.
3. Віджет поле зі списком.

1. Віджет список

Віджет Listbox (список) використовується для відображення списку


елементів, з якого користувач може вибрати декілька елементів:

from tkinter import *

tk = Tk()
tk.title('Listbox_1')
tk.geometry("180x200")

lbl = Label(tk, text="List of PL's names")


lbl.grid(row=0)

lst = Listbox(tk)
102
lst.grid(row=1)
lst.insert(1, 'Python')
lst.insert(2, 'Java')
lst.insert(3, 'C++')
lst.insert(4, 'Any other')

#lst.delete(3)

tk.mainloop()

Результат:

Спроба використати розширення ttk модуля tkinter для створення


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

lst1 = ttk.Listbox(tk)
AttributeError: module 'tkinter.ttk' has no attribute
'Listbox'

Приклад 1. Створити програму, в результаті роботи якої користувачеві


надається можливість серед запропонованих обрати елемент списку. Після
обрання елемента і натиснення на кнопку «print selection» мітка
повинна відобразити вибраний елемент.

from tkinter import *

window = Tk()
window.title('My Window')

window.geometry('500x300')

def print_selection():
103
value = lst.get(lst.curselection())
var1.set(value)

var1 = StringVar()
l = Label(window, bg='green', fg='yellow',font=('Arial',
12),
width=10, textvariable=var1)
l.pack()

b1 = Button(window, text='print selection', width=15,


height=2,
command=print_selection)
b1.pack()

var2 = StringVar()
var2.set((1,2,3,4))
lst = Listbox(window, listvariable=var2)

list_items = [11,22,33,44]
for item in list_items:
lst.insert('end', item)
lst.insert(1, 'first')
lst.insert(2, 'second')
lst.delete(2)
lst.pack()

window.mainloop()

Результат:

104
Метод curselection() повертає кортеж індексів вибраних елементів.

2. Віджет прокрутка

Віджет Scrollbar (прокрутка) використовується для реалізації


вертикального прокручування віджетів, таких як Listbox, Text та Canvas. На
віджетах Entry можна створювати горизонтальні смуги прокрутки:

from tkinter import *

tk = Tk()
tk.title('Scrollbar_1')
tk.geometry("200x180")

lst = Listbox(tk)
lst.grid(row=0, column=0)

scr = Scrollbar(tk, command=lst.yview, orient=VERTICAL)


scr.grid(row=0, column=1, sticky='ns')
lst.configure(yscrollcommand=scr.set)

for line in range(100):


lst.insert(END, 'This is line number_' + str(line))

mainloop()

Результат:

Спроба використати розширення ttk модуля tkinter для створення


віджета Scrollbar не дала видимого ефекту.

105
Приклад 2. Створити програму, в результаті роботи якої користувачеві
надається можливість додавати та видаляти елементи до списку мов
програмування.

from tkinter import *

tk = Tk()
tk.title("Program lang Add Delete")

# додавання нового елемента


def add():
new_lang = lang_entry.get()
lang_listbox.insert(0, new_lang)

# видалення виділенного елемента


def delete():
selection = lang_listbox.curselection()
lang_listbox.delete(selection[0])

# текстове поле та кнопка додавання до списку


lang_entry = Entry(width=40)
lang_entry.grid(column=0, row=0, padx=6, pady=6)
add_button = Button(text="Add",
command=add).grid(column=1, row=0, padx=6, pady=6)

# створення списку з прокруткою


lang_listbox = Listbox()
lang_listbox.grid(row=1, column=0, columnspan=2,
sticky=W+E, padx=5, pady=5)

scr = Scrollbar(tk, command=lang_listbox.yview,


orient=VERTICAL)
scr.grid(row=1, column=1, sticky='ns')
lang_listbox.configure(yscrollcommand=scr.set)

# наповнення списку
languages = ["Python", "JavaScript", "C#", "Java", "C/C+
+", "Swift",
"PHP", "Visual Basic.NET", "F#", "Ruby",
"Rust", "R", "Go",
"T-SQL", "PL-SQL", "Typescript"]

for language in languages:


lang_listbox.insert(END, language)
106
# кнопка видалення зі списку
delete_button = Button(text="Delete",
command=delete).grid(row=2, column=1, padx=5, pady=5)

mainloop()

Результат:

3. Віджет поле зі списком

Віджет Combobox є комбінацією Listbox та Entry. Цей віджет містить


стрілку вниз для вибору зі списку елементів. Коли користувач натискає
стрілку спадного меню у полі введення, з’являється список. Елемент
відображається у полі введення тоді, коли його вибрано зі списку:

from tkinter import ttk

# Creating tkinter window


window = Tk()
window.title('Combobox')
window.geometry('500x250')

# label text for title


ttk.Label(window, text = "GFG Combobox Widget",
background = 'green', foreground ="white",
font = ("Times New Roman", 15)).grid(row=0, column=1)

# label
ttk.Label(window, text = "Select the Month :",
107
font = ("Times New Roman", 10)).grid(column = 0,
row = 5, padx = 10, pady = 25)

# Combobox creation
n = StringVar()
monthchoosen = ttk.Combobox(window, width = 27,
textvariable = n)

# Adding combobox drop down list


monthchoosen['values'] = (' January',
' February',
' March',
' April',
' May',
' June',
' July',
' August',
' September',
' October',
' November',
' December')

monthchoosen.grid(column = 1, row = 5)
monthchoosen.current()
#monthchoosen.current(2)
window.mainloop()

Результат:

108
Щоб при запуску програми ініціалізувати один із елементів списку,
необхідно використати monthchoosen.current(2) (буде ініціалізовано
елемент February). Спроба створити віджет Combobox без розширення ttk
модуля tkinter призвела до отримання повідомлення про помилку:

monthchoosen = Combobox(window, width=27, textvariable=n)


NameError: name 'Combobox' is not defined

Приклад 3. Створити програму, в результаті роботи якої користувачеві


надається можливість обрати елемент поля зі списком. Після обрання
елемента і натиснення на кнопку «Click Here» на полотні з’являється мітка
з назвою вибраного елемента.

from tkinter import*


from tkinter import ttk

# Creating tkinter window and set dimensions


window = Tk()
window.title('Combobox')
window.geometry('500x250')

def callback():
l2.configure(text=country.get())

# label text for title


ttk.Label(window, text = "Choose the country and vote for
them",
background = 'cyan', foreground ="black",
font = ("Times New Roman", 15)).grid(row=0, column=1)

# Set label
ttk.Label(window, text = "Select the Country :",
font = ("Times New Roman", 12)).grid(column = 0,
row = 5, padx = 5, pady = 25)

# Create Combobox
n = StringVar()
country = ttk.Combobox(window, width=27, textvariable=n)

# Adding combobox drop down list


country['values'] = (' India',
' China',
' Australia',
' Nigeria',

109
' Malaysia',
' Italy',
' Turkey',
' Canada')

country.grid(column = 1, row = 5)
country.current()

btn=Button(window,text="Click Here",command=callback)
btn.grid(column=1, row=6)

l2=Label(window,text="",font = ("Times New Roman", 15))


l2.grid(column=1, row=9, padx = 5, pady = 25)

window.mainloop()

Результат:

Практичні завдання

Завдання 1. Розробити програму, в результаті роботи якої створюється


список (Listbox), елементами якого є 30 випадкових чисел. Додати до
списку прокрутку.
Або
Розробити програму, в результаті роботи якої створюється список
(Listbox), елементами якого є 30 значень поточного часу. Додати до списку
прокрутку. Один із можливих підходів до розв’язання завдання представлено
на рисунку:

110
Примітка. Для отримання поточного часу необхідно скористатися методом
datetime модуля datetime та методом sleep модуля time. Детальніше за
адресою https://www.programiz.com/python-programming/datetime/current-time

Завдання 2. Доопрацювати приклад 3 лекції так, щоб після вибору країни


та натиснення на кнопку, з’являлася назва столиці вибраної країни.

Завдання 3. Створити програму, в результаті роботи якої користувачеві


надається можливість вибрати елемент поля зі списком. Після натиснення
на кнопку на полотні відбувається зміна. Наприклад:
 змінюється атрибут text мітки;
 змінюється колір фону або тексту мітки;
 з’являється / зникає рамка навколо мітки;
 з’являється / зникає мітка (мітка може бути представлена у
вигляді картинки);
 з’являється інформаційне вікно;
 інше.

Один із можливих підходів до розв’язання завдання представлено


на рисунку:

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

Форма облікової картки повинна містити


 Label, Entry, Button (обов’язково)
 картинку (обов’язково),
 Checkbutton, Radiobutton, Listbox, Scrollbar, Combobox (один або
кілька із зазначених віджетів).

На формі реалізувати обчислення. Наприклад:


 за введеною сумою покупки обчислити та вивести знижку,
 за введеною назвою пакета послуг обчислити та вивести знижку /
пільгу,
 за введеною кількістю років роботи обчислити та вивести доплату
за стаж,
 за введеною назвою пільги обчислити та вивести знижку на
вартість страхового полісу,
112
 за введеною назвою порушення ПДР обчислити та вивести суму
штрафу,
 інше.

Контрольні запитання
1. Для чого призначений інструментарій Tk GUI. Як його підключити до
Python-програми?
2. Чим характеризується віджети Список, Прокрутка, Поле зі списком? До
якого класу модуля tkinter вони належать?
3. Для чого призначений метод curselection()?
4. Чи можна використати віджет Поле зі списком без підключення
розширення ttk модуля tkinter?
5. Які вбудовані менеджери розмітки є в модулі tkinter. Назвіть
особливості використання менеджера grid.
6. Яке призначення кнопки у наступному коді?

from tkinter import *


def hide_show ():
if label.winfo_viewable ():
label.grid_remove ()
else:
label.grid ()
root = Tk ()
label = Label (text='Вітаю! ')
label.grid ()
button = Button (command = hide_show, text = "Кнопка")
button.grid ()
root.mainloop ()

7. Які необхідно внести зміни у наступний код, щоб була можливість вибору
довільної кількості елементів списку?

from tkinter import *


tk = Tk ()
listbox1 = Listbox (tk, height=3, width=15, selectmode =

SINGLE)
list1 = ["Київ","Харків","Одеса","Львів","Кропивницький"]
for i in list1:
listbox1.insert (END, i)
listbox1.pack ()
tk.mainloop ()

113
Розділ ІІІ. Візуалізація даних
Тема №10. Бібліотека Matplotlib. Графіки функцій
Мета: формування вмінь створення графіків функцій засобами бібліотеки
Matplotlib.

Теоретичні питання

План
1. Загальні поняття
2. Побудова кількох графіків на одному рисунку (полотні)

1. Загальні поняття

Іноді, щоб зробити висновки, необхідно візуалізувати дані, і Matplotlib -


один з інструментів візуалізації для користувачів Python. Matplotlib – це
потужна бібліотека для побудови графіків, корисна для тих, хто працює з
Python та NumPy. Найбільш використовуваним модулем Matplotib є Pyplot.
Графік Matplotlib можна розділити на кілька частин, тому є поняття
Figure.

Рисунок (Figure). Це єдина фігура, яка може містити кілька осей


(графіків, систем координат). Можна уявити фігуру як полотно, яке містить
графіки (рис. 3.1).

Осі (як система координат). Ще можна назвати сюжетом. Фігура може


містити багато осей – дві або три (у випадку 3D) об’єктів. Кожна вісь має
заголовок, мітку x та мітку y.

Вісь. Є числовою лінією, визначає межі графіків.

Композиція. Усі екземпляри, що можна побачити на малюнку –текстові


об’єкти, об’єкти Line2D, об’єкти колекції.

114
Рис. 3.1. Об’єкт Рисунок (Figure)

Приклад 1. Розглянемо програму побудови найпростішого графіка:

import matplotlib.pyplot as plt


import numpy as np

# визначення значень x, y та побудова графіка


plt.plot([1,2,3,4],[1,4,9,16])

# створення заголовку
plt.title("The First Plot")

# створення підписів для осей


plt.xlabel("X label")
plt.ylabel("Y label")

plt.show()

115
Результат:

Можна вказати розмір малюнка, використовуючи метод figure() з


аргументом figsize (довжини рядків і стовпців передаються як значення
кортежу). Додамо рядки програмного коду до програми, розглянутої вище:


import numpy as np

# визначення розміру графіка


plt.figure(figsize=(15,5))

# визначення значень x, y та побудова графіка


plt.plot([1,2,3,4],[1,4,9,16])

Результат:

116
З аргументами X та Y можна передавати необов’язковий третій аргумент
у вигляді рядка, який вказує колір та тип лінії графіка. Формат за
замовченням є b-, що означає суцільну синю лінію. Використаємо go, що
означає зелені кола:

plt.plot([1,2,3,4],[1,4,9,16], "go")

Результат:

Можна застосувати маркери для графіка:

plt.plot([1,2,3,4],[1,4,9,16], marker = "o")


117
Результат:

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


https://www.w3schools.com/python/matplotlib_markers.asp .

Можна побудувати декілька кривих в одному графіку, передавши


набори аргументів X та Y у метод plot():


# визначення значень x, y та побудова графіка
x = np.arange(1,5)
y = x**3
plt.plot([1,2,3,4],[1,4,9,16], x,y, marker = "^")

Результат:

118
Можна визначити межі для осей:

# визначення значень x, y та побудова графіка
x = np.arange(1,5)
y = x**3
plt.plot([1,2,3,4],[1,4,9,16], x,y, marker = "^")
plt.axis([0, 6, 0, 70])

Результат:

119
Приклад 2. Розглянемо ще один підхід до побудови декількох кривих в
одному графіку:

import matplotlib.pyplot as plt


import numpy as np

# визначення значень змінної t


t=np.arange(0,5,0.2)

# побудова графіків трьох функцій


plt.plot(t,t,'r--', label='y = x')
plt.plot(t,t**3,label='y = x^3')
plt.plot(t,t**2,'gs',label='y = x^2')

# створення заголовку та підписів для осей


plt.title("The Second Plot")
plt.xlabel("X label")
plt.ylabel("Y label")

# створення легенди
120
plt.legend(loc='best')

plt.show()

Результат:

Додамо сітку до графіка за допомогою команди

# створення легенди
plt.legend(loc='best')

# створення сітки
plt.grid()

plt.show()

Результат:

121
Форматування сітки здійснюється, наприклад, так:

plt.grid(color = 'green', linestyle = '--', linewidth = 0.5)

Функція linspace() модуля numpy


Повертає рівномірно розташовані числа у вказаному інтервалі. Її зручно
використовувати для побудови графіків:

import numpy as np
import matplotlib.pyplot as plt

N = 8
y = np.zeros(N)

x1 = np.linspace(0, 10, N, endpoint=True)


x2 = np.linspace(0, 10, N, endpoint=False)

plt.plot(x1, y, 'o')
plt.plot(x2, y + 0.5, 'o')

122
plt.ylim([-0.5, 1])

plt.show()

Тут np.zeros(N) повертає масив розмірністю N, заповнений нулями.


Результат:

Приклад 3. Побудувати графіки функцій cos(X), sin(X)

import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)


print(X)
cos, sin = np.cos(X), np.sin(X)

plt.plot(X, cos, color='blue', label="cosine")


plt.plot(X, sin, color='red', label="sine")
plt.legend(loc='upper left', frameon=False)

plt.show()
123
Результат:

2. Побудова кількох графіків на одному рисунку (полотні)


Можна використовувати метод subplot(), щоб додати більше одного
графіка на одному рисунку. Метод subplot() приймає три аргументи: nrows,
ncols та index. Вони вказують кількість рядків, кількість стовпців та номер
індексу підграфіка. Наприклад, необхідно створити два підграфіки на одному
рисунку так, щоб вони були в одному рядку та у двох стовпцях, тому до
методу subplot() передаються аргументи (1,2,1) та (1,2,2). Метод title()
використовується для підграфіків, метод suptitle() для загального заголовока:

plt.subplot(1,2,1)
plt.plot([1,2,3,4],[1,4,9,16],"go")
plt.title("1st Subplot")

plt.subplot(1,2,2)
x = np.arange(1,5)
y = x**3
plt.plot(x,y, "r^")
plt.title("2nd Subplot")

plt.suptitle("My Sub-plots")
124
plt.show()

Два рядки, один стовпець:


plt.subplot(2,1,1)
plt.plot([1,2,3,4],[1,4,9,16],"go")
plt.title("1st Subplot")

plt.subplot(2,1,2)
x = np.arange(1,5)
y = x**3
plt.plot(x,y, "r^")
plt.title("2nd Subplot")

Результат:

125
Більш зручним є використання методу subpltots(). Цей метод приймає
два аргументи nrow і ncols як кількість рядків і кількість стовпців відповідно,
створює два об'єкти: фігура та осі (системи координат), які зберігаються у
змінних fig та ax, які можна використовувати для зміни атрибутів рівня
фігури та осей відповідно. Зверніть увагу, що ці імена змінних вибирані
довільно:

import matplotlib.pyplot as plt


import numpy as np

x = np.arange(1,5)
y = x**3

fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(6,6))


##print(fig)
##print(ax)
126
ax[0,1].plot([1,2,3,4],[1,4,9,16], color = "green", marker
= "o")
ax[1,0].plot(x,y, color = "red", marker = "^")
ax[0,1].set_title("Squares")
ax[1,0].set_title("Cubes")

plt.suptitle("My Sub-plots")

plt.show()

Також є можливим такий варіант:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-3*np.pi, 3*np.pi, 200)


127
y = np.sinc(x)

fig = plt.figure()

ax_1 = fig.add_subplot(2, 1, 1)
ax_2 = fig.add_subplot(2, 2, 3)
ax_3 = fig.add_subplot(2, 2, 4)

ax_1.plot(x, y)
ax_1.grid(axis = 'x')
ax_1.set_title('axis = "x"')

ax_2.plot(x, y)
ax_2.grid(axis = 'y')
ax_2.set_title('axis = "y"')

ax_3.plot(x, y)
ax_3.grid(axis = 'both')
ax_3.set_title('axis = "both"')

fig.set_figwidth(12)
fig.set_figheight(12)

plt.show()

Результат:

128
Практичні завдання

Завдання 1. Побудувати графіки функцій (в одній системі координат)


згідно варіанту. Додати сітку, застосувати форматування.
Варіант

Варіант

Функції Проміжок Функції Проміжок

2
y 1= x +1
5
y 1=|x| 2
y 2= x +2
5
1. y 2=| x|+1 x[-4, 5] 2. x [0, 5]
2
y 3=¿ 2 x∨¿ y 4 =|2 x|+ 1 y 3= x +3
5
2
y 4 = x+ 4
5

129
2
y 1=2 x y 1= x
3
x+1
y 2=2 y 2 =4
3. x x[-5, 2] 4. y 3=−3 x +22 x [2.5, 9.5]
y 3=−2
y 4 =−2
x−1 −2
y4 = x+ 8
3

2
y 1= x +1
y 1=2 x 2 5
2
y 2=x −2
y 2= x +2
1 2 5
5. y3= x x[-4, 5] 6. 2 x [-5, 5]
2 y 3= x +3
1
2 5
y4= x −2
3 y4= x+ 4
5

2
3
y 1=x +2 y 1= x
3
y 2=x 3+1 y 2=3 x−14
7. x[-4, 5] 8. y 3=−3 x +22 x [2.5, 9.5]
y 3=x 3
y 4 =x 3−1 −2
y4 = x+ 8
3

y 1=√ 0,5 x y 1=√ 0,5 x


y 2= √ x y 2= √ x
9. y 3= √ 2 x
x[0, 5] 10. y 3= √ x−3
x[0, 5]
y 4=√ 4 x y 4 =√ x+ 2

y 1=|x|
y 1=¿ 2 x−1∨¿ y 2=2 x−1 y 2=|x−3|
11. x[-4, 4] 12. x[-5, 5]
¿ y 3=−|x −3|
y 4 =−|x−3|+1

y 1=x 2
y 1=2 x−2 y 2=x
3

13. y 2=|2 x−2| x[-4, 4] 14. 3 x[-5, 5]


y 3=(−x)
¿ 2
y 4=−x

Завдання 2. Додати легенду до графіків завдання 1. Використовуючи


параметр loc, зробити її прозорою та змістити від початку координат.
Завдання 3. Побудувати графіки функцій завдання 1 на одному полотні
аналогічно до того, як показано на рисунку:

130
Завдання 4. Побудувати графік функції f(x) згідно варіанту. Знайти
екстремуми функції. Додати до графіка кольорову стрілку, яка буде
вказувати на екстремуми функції.
№ варіанту

№ варіанту

f(x) f(x) Стиль стрілки

1. x3 x2 2. f ( x )=3 x 2−8 x−16


( )
f x = + −2 x +3
3 2
3. 3 2
f ( x )=2 x −3 x −12 x+ 1 4. 2
f ( x )=4 x −16 x +7

5. 2
f ( x )=2 x −4 x+5 6. f ( x )=6−x −12 x
2

7. f ( x )=4+ 8 x −2 x
2 8. 1 2
f ( x )= x −2 x
4
9. 2
f ( x )=x ( x−4)
2 10. 4
f ( x )=x −2 x −3
2

11. 2
f ( x )=x +6 x−7 12. 2
f ( x )=x +6 x +8

13. 2
f ( x )=x −2 x +3 14. 2
f ( x )=−x +6 x−1

131
Завдання 5. Додати до графіку завдання 4 напис plt.title згідно
варіанту:

2)
1) 3)

4) 6)
5)

7) 8)
9)

10) 11) 12)

132
13) 14)

Контрольні запитання
1. Для чого необхідна бібліотека matplotlib?
2. Які засоби містить бібліотека matplotlib?
3. Які графіки можна побудувати за допомогою бібліотеки matplotlib?
4. Як побудувати графіки з однією і декількома кривими?
5. Якого стилю і кольору буде графік у3?

import matplotlib.pyplot as plt


x = [1, 5, 10, 15, 20]
y1 = [1, 7, 3, 5, 11]
y2 = [i*1.2 + 1 for i in y1]
y3 = [i*1.2 + 1 for i in y2]
y4 = [i*1.2 + 1 for i in y3]
plt.plot(x, y1, '-', x, y2, '--', x, y3, '-.', x, y4, ':')
plt.show()

6. Який вигляд матиме текст "HELLO!" у результаті виконання наступного


коду?

import matplotlib.pyplot as plt


bbox_properties=dict(
boxstyle="darrow, pad=0.3",
ec="k",
fc="y",
ls="-",
lw=3
)
plt.text(2, 7, "HELLO!", fontsize=15,
bbox=bbox_properties)
plt.plot(range(0,10), range(0,10))
plt.show()

133
134
Тема №11. Моделювання засобами комп’ютерної графіки
Мета: формування вмінь побудови математичних та комп’ютерних моделей
та створення діаграм засобами бібліотеки Matplotlib.

Теоретичні питання
План
1. Побудова стовпчастих діаграм
2. Побудова кругових діаграм
3. Побудова графіків розсіювання

1. Побудова стовпчастих діаграм


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

import matplotlib.pyplot as plt


import numpy as np

city=['Delhi','Beijing','Washington','Tokyo','Kyiv']
pos = np.arange(len(city))
Happiness_Index=[60,40,70,65,50]

plt.bar(pos,Happiness_Index,color='blue',edgecolor='black'
)
plt.xticks(pos, city)
plt.xlabel('City', fontsize=16)
plt.ylabel('Happiness_Index', fontsize=16)
plt.title('Barchart - Happiness index across
cities',fontsize=20)

plt.show()

Тут xticks() – отримати або встановити поділки та мітки на осі x.


Параметр rotation=30 дає можливість повернути підпис осі x на 30
градусів.

135
Результат:

Горизонтальна гістограма

Використати
plt.barh(pos,Happiness_Index,color='blue',edgecolor='black')

Складена гістограма з легендою:

import matplotlib.pyplot as plt


import numpy as np

city=['Delhi','Beijing','Washington','Tokyo','Kyiv']
Gender=['Male','Female']
pos = np.arange(len(city))
Happiness_Index_Male=[60,40,70,65,45]
Happiness_Index_Female=[30,60,70,55,55]

plt.bar(pos,Happiness_Index_Male,color='blue',edgecolor='b
lack')

136
plt.bar(pos,Happiness_Index_Female,color='pink',edgecolor=
'black',
bottom=Happiness_Index_Male)
plt.xticks(pos, city)
plt.xlabel('City', fontsize=16)
plt.ylabel('Happiness_Index', fontsize=16)
plt.title('Stacked Barchart - Happiness index across
cities',fontsize=18)
plt.legend(Gender,loc=2)
plt.show()

Результат:

Згрупована гістограма з легендою


plt.bar(pos,Happiness_Index_Male,bar_width,color='blue',ed
gecolor='black')
plt.bar(pos+bar_width,Happiness_Index_Female,bar_width,col
or='pink',

137
edgecolor='black')

Результат:

2. Побудова кругових діаграм

Кругові діаграми створюються за допомогою методу pie(). Можна


передавати аргументи для форматування: додавання тіні, виокремлення
частини, нахил під кутом тощо.
Приклад 2. Побудувати кругову діаграму щільності населення у різних
країнах світу:

import matplotlib.pyplot as plt

values = [60, 80, 90, 55, 10, 30]


colors = ['b', 'g', 'r', 'c', 'm', 'y']
labels = ['US', 'UK', 'India', 'Germany', 'Australia',
'South Korea']
explode = (0.2, 0, 0, 0, 0, 0)
plt.pie(values, colors=colors, labels= values,
explode=explode,
138
counterclock=False, shadow=True)
plt.title('Population Density Index')
plt.legend(labels,loc=3)
plt.show()

Тут counterclock() – встановити напрямок розташування секторів за


годинниковою стрілкою або проти (значення відображаються за
годинниковою стрілкою з counterclock = False).
Результат:

Кругова діаграма зі значеннями відсотків:

plt.pie(values, colors=colors, labels=labels,


explode=explode,
autopct='%1.1f%%', counterclock=False,
shadow=True)

Результат:

139
3. Побудова графіків розсіювання

Графіки розсіювання створюються за допомогою методу scatter().


Вони широко використовуються, особливо корисні для візуалізації проблем
регресії (аналіз відносин між змінними).
Приклад 3. Побудувати діаграму розсіювання для даних про зріст і вагу.
Доцільно використати методи xlim() та ylim() для встановлення меж осей
X та Y:

import matplotlib.pyplot as plt

weight1=[63.3,57,64.3,63,71,61.8,62.9,65.6,64.8,63.1,68.3
,69.7,65.4,66.3,60.7]
height1=[156.3,100.7,114.8,156.3,237.1,123.9,151.8,164.7,
105.4,136.1,175.2,137.4,164.2,151,124.3]

plt.scatter(weight1,height1,c='b',marker='o')
plt.xlabel('weight', fontsize=16)
plt.ylabel('height', fontsize=16)
plt.title('scatter plot - height vs weight',fontsize=20)
plt.show()

Результат:
140
Графік розсіювання з групуванням:

import matplotlib.pyplot as plt


import numpy as np

weight1=[57,58.2,58.6,59.6,59.8,60.2,60.5,60.6,60.7,61.3,
61.3,61.4,61.8,61.9,62.3]
height1=[100.7,195.6,94.3,127.1,111.7,159.7,135,149.9,124
.3,112.9,176.7,110.2,123.9,161.9,107.8]

weight2=[62.9,63,63.1,63.2,63.3,63.4,63.4,63.4,63.5,63.6,
63.7,64.1,64.3,64.3,64.7,64.8,65]
height2=[151.8,156.3,136.1,124.2,156.3,130,181.2,255.9,16
3.1,123.1,119.5,179.9,114.8,174.1,108.8,105.4,141.4]

weight3=[69.2,69.2,69.4,69.7,70,70.3,70.8,71,71.1,71.7,71
.9,72.4,73,73.1,76.2]
height3=[166.8,172.9,193.8,137.4,162.4,137.1,169.1,237.1,
189.1,179.3,174.8,213.3,198,191.1,220.6]

weight=np.concatenate((weight1,weight2,weight3))
141
height=np.concatenate((height1,height2,height3))

color_array = ['b'] * 15 + ['g'] * 17 + ['r']*15

plt.scatter(weight, height, marker='*', c=color_array)

plt.xlabel('weight', fontsize=16)
plt.ylabel('height', fontsize=16)
plt.title('grouped scatter plot - height vs
weight',fontsize=20)
plt.show()

Результат:

Практичні завдання

Завдання 1. Побудувати модель польоту (згідно варіанту):


1) чавунного ядра радіуса R=0,3 м, кинутого під кутом α = 10° до
поверхні Землі зі швидкістю v0 = 50 м/с.
2) срібного ядра радіуса R=0,5 м, кинутого під кутом α = 35° до поверхні
Землі зі швидкістю v0 = 40 м/с.
3) кварцового ядра радіуса R=0,3 м, кинутого під кутом α = 15° до
поверхні Землі зі швидкістю v0 = 30 м/с.
142
4) титанового ядра радіуса R= 0,1 м, кинутого під кутом α = 65° до
поверхні Землі зі швидкістю v0 = 40 м/с.
5) мідного ядра радіуса R= 0,8 м, кинутого під кутом α = 75° до поверхні
Землі зі швидкістю v0 = 70 м/с.
6) гумового ядра радіуса R=0,7 м, кинутого під кутом α = 25° до поверхні
Землі зі швидкістю v0 = 60 м/с.
7) нікелевого ядра радіуса R= 0,1 м, кинутого під кутом α = 65° до
поверхні Землі зі швидкістю v0 = 80 м/с.
8) золотого ядра радіуса R= 0,1 м, кинутого під кутом α = 30° до
поверхні Землі зі швидкістю v0 = 100 м/с.
9) олов’яного ядра радіуса R= 0,5 м, кинутого під кутом α = 30° до
поверхні Землі зі швидкістю v0 = 70 м/с.
10) алюмінієвого ядра радіуса R=0,6 м, кинутого під кутом α = 60° до
поверхні Землі зі швидкістю v0 = 80 м/с.
11) срібряного ядра радіуса R= 0,3 м, кинутого під кутом α = 55° до
поверхні Землі зі швидкістю v0 = 100 м/с.
12) стального ядра радіуса R= 0,4 м, кинутого під кутом α = 35° до
поверхні Землі зі швидкістю v0 = 80 м/с.
13) чавунного ядра радіуса R= 0,1 м, кинутого під кутом α = 30° до
поверхні Землі зі швидкістю v0 = 55 м/с.
14) титанового ядра радіуса R= 0,1 м, кинутого під кутом α = 60° до
поверхні Землі зі швидкістю v0 = 30 м/с.

Завдання 2. Дослідити тенденціі вступу до ЦДПУ ім  В. Винниченка та ще


одного з ВНЗ України на спеціальність згідно варіанту за останні п’ять
років (результати подати у вигляді гістограми):
1) 122 Комп’ютерні науки
2) 014.04 Середня освіта (Математика)
3) 014.08 Середня освіта (Фізика)
4) 014.09 Середня освіта (Інформатика)
5) 014.10 середня освіта (Трудове навчання та технології)
6) 112 Статистика
7) 012 Дошкільна освіта
8) 013 Початкова освіта
9) 016 Спеціальна освіта
10) 053 Психологія
11) 231 Соціальна робота
12) 014.05 Середня освіта (Біологія та здоров'я людини)
13) 014.07 Середня освіта (Географія)
14) 014.15 Середня освіта (Природничі науки) 

143
Завдання 3. Визначити у відсотковому співвідношенні кількість студентів,
що навчаються на кожній із спеціальностей вказаного варіанту курсу і
факультету ЦДПУ ім. В.Винниченка, подати результати у вигляді
кругової діаграми:
1) І курс фізико-математичного факультету,
2) ІІ курс фізико-математичного факультету,
3) ІІІ курс фізико-математичного факультету,
4) ІV курс фізико-математичного факультету,
5) І курс природничо-географічного факультету,
6) ІІ курс мистецького факультету,
7) І курс факультету психології та педагогіки,
8) ІІ курс факультету психології та педагогіки,
9) ІІІ курс природничо-географічного факультету,
10) ІV курс факультету психології та педагогіки,
11) І курс факультету фізичного виховання,
12) І курс факультету іноземних мов,
13) І курс факультету історії та права,
14) І курс факультету філології та журналістики.

Контрольні запитання

1. Які засоби надаються бібліотекою NumPy?


2. Як побудувати точкові графіки?
3. Як побудувати стовпчасті діаграми?
4. Як побудувати секторні діаграми?
5. Як налаштувати кольори елементів діаграми?
6. Які властивості ліній?
7. Які необхідно внести зміни у наступний код, щоб маркером графіку
розсіювання був ?

import matplotlib.pyplot as plt


import numpy as np
x = np.random.randn(1000)
y = np.random.randn(1000)
size = 50*np.random.randn(1000)
colors = np.random.rand(1000)
plt.scatter(x, y, s=size, c=colors)
plt.show()

144
Рекомендовані джерела

1. The Python Standard Library [Electronic recourse]. – Access mode:


https://docs.python.org/3/library/index.html
2. The Python Tutorial [Electronic recourse]. – Access mode:
https://docs.python.org/3/tutorial/index.html

145

You might also like