12. Класи та об’єкти
Клас — це форма, за якою створюються об’єкти. Об’єкт називають екземпляром класу.

Примітка: папка [shared] була розміщена в папці [Sources Root] проекту.
12.1. Скрипт [classes_01]: клас «Об’єкт»
Скрипт [classes_01] демонструє застаріле використання класів:
# клас
class Objet(object):
"""une classe Objet vide"""
# будь-яка змінна типу [Objet] може мати атрибути за своєю структурою
obj1 = Objet()
obj1.attr1 = "un"
obj1.attr2 = 100
# відображає об’єкт
print(f"objet1=[{obj1}, {type(obj1)},{id(obj1)},{obj1.attr1},{obj1.attr2}]")
# змінює об’єкт
obj1.attr2 += 100
# виводить об’єкт
print(f"objet1=[{obj1.attr1},{obj1.attr2}]")
# присвоює посилання obj1 об’єкту obj2
obj2 = obj1
# змінює об’єкт, на який вказує obj2
obj2.attr2 = 0
# виводить обидва об’єкти — obj1 тепер вказує на змінений об’єкт
print(f"objet1=[{obj1.attr1},{obj1.attr2}]")
print(f"objet2=[{obj2.attr1},{obj2.attr2}]")
# obj1 та obj2 вказують на один і той самий об’єкт
print(f"objet1=[{obj1}, {id(obj1)},{obj1.attr1},{obj1.attr2}]")
print(f"objet2=[{obj2}, {id(obj2)},{obj2.attr1},{obj2.attr2}]")
print(obj1 == obj2)
# тип екземпляра obj1
print(f"type(obj1)={type(obj1)}")
print(f"isinstance(obj1,Objet)={isinstance(obj1, Objet)}, isinstance(obj1,object)={isinstance(obj1, object)}")
# у Python кожен тип є об’єктом
print(f"type(4)={type(4)}")
print(f"isinstance(4, int)={isinstance(4, int)}, isinstance(4, object)={isinstance(4, object)}")
Примітки:
- рядки 2–3: порожній клас [Objet];
- рядок 2: клас можна оголосити у трьох формах:
- class Об'єкт;
- class Об'єкт();
- class Об'єкт(object);
- рядок 3: ще один вид коментаря. Коментар, що починається з трьох символів «, може займати кілька рядків;
- рядок 7: створення екземпляра класу Objet. Результатом є адреса, як показано в рядках 24–26;
- рядки 8–9: пряма ініціалізація двох атрибутів об’єкта;
- рядок 17: копіювання посилань. Змінні obj1 та obj2 — це два покажчики (посилання) на один і той самий об’єкт;
- рядок 19: змінюється об’єкт, на який вказує [obj2]. Оскільки [obj1] та [obj2] вказують на один і той самий об’єкт, виведення об’єкта [obj1, obj2] у рядках 21 та 22 покаже, що об’єкт, на який вказує [obj1], змінився;
- рядки 24–26: ці рядки призначені для демонстрації рівності змінних [obj1] та [obj2]. Це буде видно після виведення рядка 26. У цьому порівнянні рівні адреси [obj1] та [obj2];
- кожен об’єкт Python ідентифікується за допомогою унікального номера, який отримується за допомогою виразу [id(objet)]. Рядки 24 і 25 покажуть, що номери об’єктів, на які вказують [obj1] та [obj2], є однаковими, що свідчить про те, що ці дві посилання вказують на один і той самий об’єкт;
- рядки 27–29: функція [isinstance(expr,Type)] повертає логічне значення True, якщо вираз [expr] має тип [Type]. Тут ми побачимо, що [obj1] має тип [Objet], що здається природним, але також має тип [object]. Клас [object] є батьківським класом для всіх класів Python. Згідно з властивістю успадкування класів, дочірній клас F має всі властивості свого батьківського класу P, і функція [isinstance(instance de F, P)] повертає True;
- рядки 30–32: показують, що тип [int] також є типом [object]. Усі типи Python походять від класу [object];
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_01.py
objet1=[<__main__.Objet object at 0x0000025C3F469BB0>, <class '__main__.Objet'>,2595221838768,un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]
objet1=[<__main__.Objet object at 0x0000025C3F469BB0>, 2595221838768,un,0]
objet2=[<__main__.Objet object at 0x0000025C3F469BB0>, 2595221838768,un,0]
True
type(obj1)=<class '__main__.Objet'>
isinstance(obj1,Objet)=True, isinstance(obj1,object)=True
type(4)=<class 'int'>
isinstance(4, int)=True, isinstance(4, object)=True
Process finished with exit code 0
12.2. Скрипт [classes_02]: клас Personne
Скрипт [classes_02] демонструє, що атрибути класу є публічними: до них можна отримати доступ безпосередньо ззовні класу. Це ще один приклад використання класів, від якого не рекомендується відходити. Проте ми наводимо його, оскільки іноді можна натрапити на такий тип коду (Python його підтримує), і тоді потрібно вміти його розуміти.
# клас «Людина»
class Personne:
# атрибути класу
# не оголошені — можуть створюватися динамічно
# метод
def identité(self: object) -> str:
# апріорі використовує атрибути, яких не існує
return f"[{self.prénom},{self.nom},{self.âge}]"
# ---------------------------------- main
# атрибути є публічними і можуть створюватися динамічно
# інстанціювання класу
p = Personne()
# пряма ініціалізація атрибутів класу
p.prénom = "Paul"
p.nom = "de la Hûche"
p.âge = 48
# виклик методу класу
print(f"personne={p.identité()}")
# тип екземпляра p
print(f"type(p)={type(p)}")
print(f"isinstance(Personne)={isinstance(p, Personne)}, isinstance(object)={isinstance(p, object)}")
Примітки:
- рядки 2–9: клас із методом;
- рядок 7: перший параметр будь-якого методу класу повинен бути об’єктом self, який позначає поточний об’єкт. Метод [identité] повертає рядок символів;
- рядок 15: створення екземпляра об’єкта [Personne];
- рядки 16–19: показують, що атрибути об’єкта можуть створюватися динамічно (вони не існують у визначенні класу);
- рядок 9: атрибути класу позначаються за допомогою нотації [self.attribut];
- рядки 23–24 покажуть, що об’єкт [p] є одночасно екземпляром класу [Personne] і класу [object];
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_02.py
personne=[Paul,de la Hûche,48]
type(p)=<class '__main__.Personne'>
isinstance(Personne)=True, isinstance(object)=True
Process finished with exit code 0
12.3. Скрипт [classes_03]: клас Personne з конструктором
Скрипт [classes_03] демонструє типове використання класу:
# клас «Особа»
class Personne:
# конструктор — ініціалізує три атрибути
def __init__(self: object, prénom: str, nom: str, âge: int):
# ім'я: ім'я особи
# прізвище: прізвище особи
# вік: вік особи
self.prénom = prénom
self.nom = nom
self.âge = âge
# повертає атрибути класу у вигляді символьного рядка
def identité(self: object) -> str:
return f"[{self.prénom},{self.nom},{self.âge}]"
# ---------------------------------- main
# об’єкт «Особа»
p = Personne("Paul", "de la Hûche", 48)
# виклик методу
print(f"personne={p.identité()}")
Примітки:
- рядок 4: конструктор класу називається __init__. Як і в інших методах, його першим параметром є self;
- рядок 20: об’єкт Personne створюється за допомогою конструктора класу;
- рядки 13–15: метод [identité] повертає рядок, що представляє вміст об’єкта;
- рядок 22: виведення імені особи;
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_03.py
personne=[Paul,de la Hûche,48]
Process finished with exit code 0
12.4. Скрипт [classes_04]: статичні методи
У папці [modules] ми визначаємо наступний клас [Utils] (utils.py):

class Utils:
# статичний метод
@staticmethod
def is_string_ok(string: str) -> bool:
# чи є string рядком
erreur = not isinstance(string, str)
if not erreur:
# чи порожній рядок?
erreur = string.strip() == ''
# результат
return not erreur
Примітки
- рядок 3: анотація [@staticmethod] вказує, що метод, позначений цією анотацією, є методом класу, а не методом екземпляра. Про це свідчить той факт, що першим параметром такого методу не є ключове слово [self]. Отже, статичний метод не має доступу до атрибутів об’єкта. Замість того, щоб писати:
пишемо
Оскільки вище ми написали [Utils.is_string_ok], метод [is_string_ok] називається методом класу (у даному випадку класу Utils). Для цього метод [Utils.is_string_ok] повинен бути позначений ключовим словом [@staticmethod].
Статичний метод [Utils.is_string_ok] дозволяє тут перевірити, чи є дані непорожнім рядком символів.
Скрипт [classes_04] використовує клас [Utils] наступним чином:
# конфігуруємо додаток
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from utilitaires import Utils
print(Utils.is_string_ok(" "))
print(Utils.is_string_ok(47))
print(Utils.is_string_ok(" q "))
- рядки 1–4: використовується скрипт конфігурації;
Скрипт конфігурації [config.py] має такий вигляд:
def configure():
import os
# папка з файлом конфігурації
script_dir = os.path.dirname(os.path.abspath(__file__))
# абсолютні шляхи до папок, які потрібно додати до syspath
absolute_dependencies = [
f"{script_dir}/shared",
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/venv/lib/site-packages",
"C:/myprograms/Python38/lib",
"C:/myprograms/Python38/DLLs"
]
# оновлення syspath
from myutils import set_syspath
set_syspath(absolute_dependencies)
# повертаємо конфігурацію
return {}
- рядок 9: папка [shared] буде додана до Python Path;
Результат виконання такий:
12.5. Скрипт [classes_05]: перевірка правильності атрибутів
Скрипт [classes_05] вводить нові поняття:
- визначення власного типу винятку;
- визначення методу [_str_], який є методом ідентичності за замовчуванням для класів;
- визначення властивостей;
# налаштування програми
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from utilitaires import Utils
# власний клас винятків, що походить від [BaseException]
class MyException(BaseException):
# нічого не робимо: порожній клас
pass
# клас Personne
class Personne:
# конструктор
def __init__(self: object, prénom: str = "x", nom: str = "y", âge: int = 0):
# ім'я: ім'я особи
# прізвище: прізвище особи
# вік: вік особи
# збереження параметрів
# ініціалізація відбуватиметься за допомогою сеттерів
self.prénom = prénom
self.nom = nom
self.âge = âge
# метод toString класу
def __str__(self: object) -> str:
return f"[{self.__prénom},{self.__nom},{self.__âge}]"
# геттери
@property
def prénom(self) -> str:
return self.__prénom
@property
def nom(self) -> str:
return self.__nom
@property
def âge(self) -> int:
return self.__âge
# сетери
@prénom.setter
def prénom(self, prénom: str):
# ім'я має бути не порожнім
if Utils.is_string_ok(prénom):
self.__prénom = prénom.strip()
else:
raise MyException("Le prénom doit être une chaîne de caractères non vide")
@nom.setter
def nom(self, nom: str):
# ім'я має бути не порожнім
if Utils.is_string_ok(nom):
self.__nom = nom.strip()
else:
raise MyException("Le nom doit être une chaîne de caractères non vide")
@âge.setter
def âge(self, âge: int):
# вік має бути цілим числом >=0
erreur = False
if isinstance(âge, int):
if âge >= 0:
self.__âge = âge
else:
erreur = True
else:
erreur = True
# помилка?
if erreur:
raise MyException("L'âge doit être un entier >=0")
# ---------------------------------- main
# об’єкт «Людина»
try:
# інстанціювання класу «Personne»
p = Personne("Paul", "de la Hûche", 48)
# виведення об’єкта p
print(f"personne={p}")
except MyException as erreur:
# виведення помилки
print(erreur)
# ще один об’єкт «Людина»
try:
# інстанціювання класу «Людина»
p = Personne("xx", "yy", "zz")
# виведення об'єкта p
print(f"personne={p}")
except MyException as erreur:
# виведення помилки
print(erreur)
# ще одна людина, цього разу без параметрів
try:
# створення екземпляра класу «Людина»
p = Personne()
# виведення об'єкта p
print(f"personne={p}")
except MyException as erreur:
# виведення повідомлення про помилку
print(erreur)
# неможливо отримати доступ до приватних атрибутів __attr класу
p.__prénom = "Gaëlle"
print(f"p.prénom={p.prénom}")
print(f"p.__prénom={p.__prénom}")
p.prénom = "Sébastien"
print(f"p.prénom={p.prénom}")
print(f"p.__prénom={p.__prénom}")
Примітки:
- рядки 10–13: клас MyException, похідний від класу BaseException (ми розглянемо цей момент трохи пізніше). Він не додає жодних функціональних можливостей до останнього. Він існує лише для того, щоб мати власний виняток;
- рядок 19: конструктор має значення за замовчуванням для своїх параметрів. Таким чином, операція p=Personne() еквівалентна p=Personne("x","y",0);
- рядки 34–45: властивості класу. Це методи, позначені ключовим словом [@property]. Вони використовуються для повернення значень атрибутів;
- рядки 47–77: методи-сеттери класу. Це методи, позначені ключовим словом [@attributsetter]. Вони використовуються для встановлення значень атрибутів;
- рядки 48–54: сеттер атрибута [prénom]. Цей метод викликатиметься щоразу, коли атрибуту [prénom] присвоюватиметься значення:
Рядок 2 спричинить виклик [p.prénom(valeur)]. Перевага використання сеттера для присвоєння значення атрибуту полягає в тому, що, оскільки сеттер є функцією, можна перевірити правильність значення, присвоєного атрибуту;
- рядок 51: перевіряється, чи значення, присвоєне атрибуту [prénom], є непорожнім рядком символів. Для цього використовується статичний метод [Utils.isStringOk], розглянутий раніше;
- рядок 52: значення, присвоєне атрибуту [prénom], очищається від «пробілів» на початку та в кінці рядка і присвоюється атрибуту [self.__prénom]. Отже, тут використовується не атрибут [prénom]. Інакше це було б неможливо, оскільки виник би нескінченний рекурсивний виклик. Можна було використати будь-яке ім’я атрибута. Використання атрибута [__prénom] із двома підкресленнями на початку ідентифікатора має особливе значення: атрибути, що починаються з двох підкреслень, є приватними для класу. Це означає, що вони не видимі ззовні класу. Тому не можна написати:
Насправді незабаром ми побачимо, що це можна написати, але це не змінює ім’я. Це робить щось інше;
- рядки 53–54: якщо значення, присвоєне імені, є неправильним, генерується виняток. Таким чином, код, що викликає, дізнається, що його виклик є неправильним;
- рядки 35–37: властивість [prénom]. Вона викликатиметься щоразу, коли в виразі буде записано [p.prénom]. У цьому випадку викликатиметься метод [p.prénom()]. У рядку 37 повертається значення атрибута [__prénom], оскільки ми побачили, що сеттер атрибута [prénom] присвоював його значення приватному атрибуту [__prénom];
- рядки 56–62: сеттер атрибута [nom] побудовано аналогічно до сеттера атрибута [prénom]. Те саме стосується сетера атрибута [âge] у рядках 64–77;
- хоча властивості [prénom, nom, valeur] не є справжніми атрибутами, якими насправді є [__prénom, __nom, __âge], ми й надалі називатимемо їх атрибутами класу, оскільки вони використовуються як такі;
- рядки 19–28: конструктор класу неявно використовує сетери атрибутів [prénom, nom, âge]. Дійсно, при записі в рядку 26 значення [self.prénom = prénom] неявним чином викликатиметься метод [prénom(self, prénom)]. Після цього буде перевірено правильність параметра [prénom]. Те саме відбудеться з двома іншими атрибутами [nom, âge];
- за цією моделлю неможливо присвоїти неправильні значення атрибутам [prénom, nom, âge] класу;
- рядки 30–32: функція __str__ замінює метод, який раніше називався identité. Назва [__str__] (2 підкреслення спереду та ззаду) не є випадковою. Про це ми дізнаємося далі;
- рядки 83–86: створення екземпляра особи, а потім відображення її ідентифікаційних даних;
- рядок 84: створення екземпляра;
- рядок 86: виведення. Операція вимагає вивести особу p у вигляді символьного рядка. Інтерпретатор Python автоматично викликає метод p.__str__(), якщо він існує. Цей метод виконує ту саму роль, що й метод toString() у Java або в мовах .NET;
- рядки 87–89: обробка можливого винятку типу MyException. Після цього виводиться повідомлення про помилку;
- рядки 91–99: те саме для другого об’єкта, інстанційованого з неправильними параметрами;
- рядки 102–109: те саме для третьої особи, інстанційованої з параметрами за замовчуванням: параметри не передаються. У цьому випадку використовуються значення за замовчуванням цих параметрів у конструкторі;
- рядки 112–117: ми зазначили, що атрибут [__prénom] є приватним, тому зазвичай недоступним ззовні класу. Ми хочемо це перевірити;
- рядки 112–114: присвоюється значення атрибуту [__prénom], після чого перевіряються значення атрибутів [__prénom] та [prénom], які зазвичай збігаються;
- рядки 115–117: операцію повторюють, цього разу ініціалізуючи атрибут [prénom];
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_05.py
personne=[Paul,de la Hûche,48]
L'âge doit être un entier >=0
personne=[x,y,0]
p.prénom=x
p.__prénom=Gaëlle
p.prénom=Sébastien
p.__prénom=Gaëlle
Process finished with exit code 0
Примітки
- рядки 5–6: бачимо, що присвоєння [p.__prénom = "Gaëlle"] не змінило значення атрибута [prénom], рядок 5;
- рядки 7–8: бачимо, що присвоєння [p.prénom = "Sébastien"] не змінило значення атрибута [__prénom], рядок 8;
Який висновок можна зробити? Ймовірно, операція [p.__prénom = "Gaëlle"] створила публічний атрибут [__prénom] для класу, але він відрізняється від приватного атрибута [__prénom], з яким здійснюються операції всередині класу;
12.6. Скрипт [classes_06]: додавання методу ініціалізації об’єкта
Скрипт [classes_06] додає метод до класу [Personne]:
# налаштування програми
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from utilitaires import Utils
#— власний клас-виняток, похідний від [BaseException]
class MyException(BaseException):
# нічого не робиться: порожній клас
pass
# клас «Особа»
class Personne:
# конструктор
def __init__(self: object, prénom: str = "x", nom: str = "y", âge: int = 0):
# ім'я: ім'я особи
# прізвище: прізвище особи
# вік: вік особи
# збереження параметрів
# ініціалізація відбуватиметься за допомогою сеттерів
self.prénom = prénom
self.nom = nom
self.âge = âge
# інший метод ініціалізації
def init_with_personne(self: object, p: object):
# ініціалізує поточний об’єкт з особою p
self.__init__(p.prénom, p.nom, p.âge)
# метод toString класу
def __str__(self: object) -> str:
return f"[{self.__prénom},{self.__nom},{self.__âge}]"
# геттери
…
# сетери
…
# ---------------------------------- main
# об’єкт «Людина»
try:
# інстанціювання класу «Людина»
p = Personne("Paul", "de la Hûche", 48)
# виведення об'єкта p
print(f"personne={p}")
except MyException as erreur:
# виведення повідомлення про помилку
print(erreur)
# ще один об’єкт «Людина»
try:
# створення екземпляра класу «Людина»
p = Personne("xx", "yy", "zz")
# виведення об'єкта p
print(f"p={p}")
except MyException as erreur:
# виведення повідомлення про помилку
print(erreur)
# ще одна людина, цього разу без параметрів
try:
# створення екземпляра класу «Людина»
p = Personne()
# виведення об'єкта p
print(f"p={p}")
except MyException as erreur:
# виведення повідомлення про помилку
print(erreur)
# ще одна людина, отримана шляхом копіювання
try:
# інстанціювання класу «Personne»
p2 = Personne()
p2.init_with_personne(p)
# виведення об'єкта p2
print(f"p2={p2}")
except MyException as erreur:
# виведення повідомлення про помилку
print(erreur)
Примітки:
- відмінність від попереднього скрипта полягає в рядках 30–33. Було додано метод initWithPersonne. Він викликає конструктор __init__. На відміну від типізованих мов, тут немає можливості мати методи з однаковою назвою, що розрізняються за типом параметрів або результатом. Тому неможливо мати кілька конструкторів, які б створювали об’єкт на основі різних параметрів, у даному випадку об’єкт типу Personne;
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_06.py
personne=[Paul,de la Hûche,48]
L'âge doit être un entier >=0
p=[x,y,0]
p2=[x,y,0]
Process finished with exit code 0
12.7. Скрипт [classes_07]: список об’єктів Personne
Тепер ми розміщуємо класи [MyException] та [Personne] у модулі, щоб мати змогу використовувати їх без необхідності переписувати їхній код:

Обидва класи будуть у модулі [myclasses.py], наведеному вище.
Скрипт [classes_07] демонструє, що можна отримати список об’єктів:
# налаштування програми
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from myclasses import Personne
# ---------------------------------- main
# створення списку об’єктів «особа»
groupe = [Personne("Paul", "Langevin", 48), Personne("Sylvie", "Lefur", 70)]
# ідентифікаційні дані цих осіб
for i in range(len(groupe)):
print(f"groupe[{i}]={groupe[i]}")
Примітки:
- рядок 7: імпортуємо клас [Personne];
- рядок 11: список об’єктів типу [Personne];
- рядки 13–14: виконується обхід цього списку для виведення кожного з його елементів;
- рядок 14: функція [print] відобразить рядок, що представляє об’єкт [groupe[i]]. За замовчуванням буде викликано метод [__str__];
Результати
C:\Users\serge\.virtualenvs\cours-python-v02\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/v-02/classes/01/classes_07.py
groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]
Process finished with exit code 0
12.8. Скрипт [classes_08]: створення класу, похідного від класу Personne
У модулі [myclasses] ми визначаємо такий клас [Enseignant]:
# клас «Викладач»
class Enseignant(Personne):
# конструктор
def __init__(self, prénom: str = "x", nom: str = "x", âge: int = 0, discipline: str = "x"):
# ім'я: ім'я особи
# прізвище: прізвище особи
# вік: вік особи
# предмет: предмет, який викладає
# ініціали батька/матері
Personne.__init__(self, prénom, nom, âge)
# інші ініціали
self.discipline = discipline
# toString
def __str__(self) -> str:
return f"enseignant[{super().__str__()},{self.discipline}]"
# властивості
@property
def discipline(self) -> str:
return self.__discipline
@discipline.setter
def discipline(self, discipline: str):
# дисципліна має бути непорожнім рядком
if Utils.is_string_ok(discipline):
self.__discipline = discipline
else:
raise MyException("La discipline doit être une chaîne de caractères non vide")
- рядок 2: оголошує клас Enseignant як похідний від класу Personne. Похідний клас має всі властивості (атрибути та методи) свого батьківського класу, а також власні;
- рядок 13: клас [Enseignant] визначає новий атрибут [discipline];
- рядок 11: конструктор похідного класу Enseignant повинен викликати конструктор батьківського класу Personne, передаючи йому очікувані параметри;
- рядок 17: функція [super()] повертає батьківський клас. Тут викликається функція [__str__] батьківського класу;
- рядки 19–30: визначаються методи getter і setter для нового атрибута [discipline];
Скрипт [classes_08] використовує клас [Enseignant] наступним чином:
# налаштовуємо додаток
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from myclasses import Personne, Enseignant
# ---------------------------------- main
# створення масиву об’єктів Personne та похідних
groupe = [Enseignant("Paul", "Langevin", 48, "anglais"), Personne("Sylvie", "Lefur", 70)]
# ідентифікаційні дані цих осіб
for i in range(len(groupe)):
print(f"groupe[{i}]={groupe[i]}")
Примітки:
- рядок 7: імпортуються класи [Personne] та [Enseignant], визначені у файлі [myclasses.py];
- рядки 11–14: визначається група осіб, ідентифікаційні дані яких потім відображаються;
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_08.py
groupe[0]=enseignant[[Paul,Langevin,48],anglais]
groupe[1]=[Sylvie,Lefur,70]
Process finished with exit code 0
12.9. Скрипт [classes_09]: другий клас, похідний від класу «Особа»
Скрипт [classes_09] вводить клас [Etudiant], похідний від класу [Personne]. Останній визначено в модулі [myclasses] наступним чином:
# клас «Студент»
class Etudiant(Personne):
# конструктор
def __init__(self: object, prénom: str = "x", nom: str = "y", âge: int = 0, formation: str = "x"):
Personne.__init__(self, prénom, nom, âge)
self.formation = formation
# toString
def __str__(self: object) -> str:
return f"étudiant[{super().__str__()},{self.formation}]"
# властивості
@property
def formation(self) -> str:
return self.__formation
@formation.setter
def formation(self, formation: str):
# назва курсу має бути непорожнім рядком
if Utils.is_string_ok(formation):
self.__formation = formation
else:
raise MyException("La formation doit être une chaîne de caractères non vide")
Скрипт [classes_09] використовує клас [Etudiant] наступним чином:
# налаштування програми
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from myclasses import Personne, Enseignant, Etudiant
# ---------------------------------- main
# створення масиву об’єктів Personne та похідних
groupe = [Enseignant("Paul", "Langevin", 48, "anglais"), Personne("Sylvie", "Lefur", 70),
Etudiant("Steve", "Boer", 22, "iup2 qualité")]
# ідентифікаційні дані цих осіб
for personne in groupe:
# відображення особи
print(personne)
Примітки:
- цей скрипт аналогічний попередньому.
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_09.py
enseignant[[Paul,Langevin,48],anglais]
[Sylvie,Lefur,70]
étudiant[[Steve,Boer,22],iup2 qualité]
Process finished with exit code 0
12.10. Скрипт [classes_10]: властивість [__dict__]
Скрипт [classes_10] містить властивість [__dict__], яку ми часто використовуватимемо надалі:
# налаштування програми
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from myclasses import Etudiant
# ---------------------------------- main
# створення студента
étudiant=Etudiant("Steve", "Boer", 22, "iup2 qualité")
# словник властивостей
print(étudiant.__dict__)
Коментарі
- рядки 1–4: налаштовується додаток;
- рядок 7: імпортується клас [Etudiant];
- рядок 11: створення екземпляра студента;
- рядок 13: використання попередньо визначеного методу [__dict__] (2 символи з підкресленням перед та після ідентифікатора);
Результати такі:
- у рядку 2 отримуємо словник, ключі якого є властивостями об’єкта з префіксом назви класу, до якого вони належать. Ми використаємо цей словник для створення мосту між об’єктом і словником;