Класи та Об’єкти
Концептуально об’єкти схожі на компоненти системи. Думайте про програму як про заводську конвеєрну лінію. На кожному кроці складання системний компонент обробляє певний матеріал, остаточно перетворюючи сировину на закінчений продукт.
Об’єкт містить дані, як-от необроблені або попередньо оброблені матеріали на кожному кроці складальної лінії, і поведінку, як-от дію, яку виконує кожен компонент складальної лінії.
Парадигма Об’єктно-Орієнтованого Програмування
Об’єктно-орієнтоване програмування - це парадигма програмування, яка надає засоби структурування програм так, що властивості та поведінка об’єднуються в окремі об’єкти.
Наприклад, об’єкт може представляти особу з такими властивостями, як ім’я, вік та адреса, а також такими поведінками, як ходьба, розмова, біг. Або він може представляти електронний лист із такими властивостями, як список одержувачів, тема , а також тіло та поведінку, як-от додавання вкладень і надсилання.
Інакше кажучи, об’єктно-орієнтоване програмування - це підхід до моделювання конкретних речей реального світу, таких як автомобілі, а також відносин між речами, такими як компанії та працівники, студенти та викладачі тощо. ООП моделює сутності реального світу як програмні об’єкти, які мають деякі дані, пов’язані з ними та можуть виконувати певні функції.
Концепції Об’єктно-Орієнтованого Програмування
Поки що ми можемо обговорити основні концепції парадигми ООП. І вони:
- інкапсуляція:
В ООП означає об’єднання даних із методами, які обробляють ці дані, або обмеження прямого доступу до деяких компонентів об’єкта.
Примітка
Механізм інкапсуляції часто плутають із приховуванням. Насправді інкапсуляція це не робить, але приховування даних доступне для нас завдяки інкапсуляції.
- наслідування:
Це механізм базування об’єкта або класу на іншому об’єкті (успадкування на основі прототипу) або класу (успадкування на основі класу), зберігаючи подібну реалізацію. Також визначається як отримання нових класів (підкласів) із існуючих такі як суперклас або базовий клас і формування їх у ієрархію класів.
- поліморфізм:
Це надання єдиного інтерфейсу для сутностей різних типів або використання одного символу для представлення кількох різних типів. Концепція запозичена з принципу в біології, згідно з яким організм або вид може мати багато різних форми чи етапи.
- абстракція:
Процес видалення або узагальнення деталей або атрибутів під час дослідження об’єктів або систем, щоб зосередити увагу на деталях більшої важливості, подібний за своєю природою до процесу узагальнення. Створення абстрактних понять-об’єктів шляхом віддзеркалення спільних рис або атрибутів різних неабстрактних об’єктів або систем дослідження є результатом процесу абстрагування.
Визначення Классу в Python
Примітивні структури даних - як-от числа, рядки, списки тощо - призначені для представлення простих фрагментів інформації, таких як вартість продукту, назва роману чи чиїсь улюблені кольори. Що, якщо ви бажаєте представити складніші речі?
Наприклад, скажімо, ви хочете відслідковувати співробітників в організації. Вам потрібно зберегти деяку базову інформацію про кожного працівника. Давайте почнемо з самого початку та спробуємо представити окремого працівника як групу змінних:
first_name = "Serhii"
last_name = "Horodilov"
job_title = "Software Engineer"
Цей підхід має низку проблем. Після того, як буде потрібно зберігати інформацію про більше ніж одну особу, ви повинні створити інший набір змінних: first_name_1
, first_name_2
тощо. Найжахливіше проблема в тому, що ці частини даних не мають жодного відношення одна до одної. Давайте спробуємо використати список
для цієї мети:
serhii = ["Serhii", "Horodilov", "Software Engineer"]
vlad = ["Vladyslav", "Ponomaryov", "Release Manager"]
З цим підходом також виникає ряд проблем.
По-перше, це може ускладнити керування великими файлами коду. Якщо ви посилаєтеся на serhii[0]
на кілька рядків від місця, де оголошено список serhii
, ви пам’ятаєте, що елемент з index 0
- це ім’я » «особи? Звичайно, ви можете використовувати структуру dict
, але…
По-друге, це може призвести до помилок, якщо не кожна особа має однакову кількість властивостей.
Чудовий спосіб зробити цей тип коду більш керованим і придатним для обслуговування - це використання класів.
Усі визначення класів у Python починаються з ключового слова class
, за яким йдуть ім’я класу та двокрапка. Будь-який код, який має відступ під визначенням класу, вважається частиною тіла класу.
class Person:
"""Person class implementation"""
Класи та Екземпляри Класу
Класи використовуються для створення визначених користувачем структур даних. Як було зазначено вище, ООП стосується об’єднання даних і поведінки. Класи визначають структури даних; кожна частина даних, об’єднаних у класи, називається властивістю або полем. Класи також визначають функції, які називаються методами, які ідентифікують поведінку та дії, які об’єкт, створений з класу, може виконувати зі своїми даними.
class Person:
"""Person class implementation"""
first_name: str = ""
last_name: str = ""
job_title: str = ""
Клас - це схема того, як щось має бути визначено. Він насправді не містить жодних даних. Клас person вище вказує, що властивості » «first_name`` і last_name
об’єднані в цей класу, але насправді він не містить імені людини.
Хоча класи є кресленнями, екземпляр - це об’єкт, створений із форми, заповненої інформацією. Подібно до того, як багато людей можуть заповнювати ту саму форму своєю унікальною інформацією, багато екземплярів можуть бути створений з одного класу.
serhii = Person()
serhii.first_name = "Serhii"
serhii.last_name = "Horodilov"
serhii.job_title = "Software Engineer"
vlad = Person()
vlad.first_name = "Vladyslav"
vlad.last_name = "Ponomaryov"
vlad.job_title = "Release Manager"
Методи
Функція, об’єднана в клас, називається методом. Існує кілька способів визначення методу класу. Наразі необхідно знати, що кожен метод отримає спеціальний аргумент у першій позиції. Цей аргумент є посилання на реальний об’єкт. За домовленістю цей аргумент називається self
.
class Person:
"""Person class implementation"""
first_name: str = ""
last_name: str = ""
job_title: str = ""
def get_fullname(self) -> str:
"""Return a person's fullname"""
return " ".join([self.first_name, self.last_name])
Ініціалізація Екземпляру з Даними
Є кілька методів, позначених подвійним підкресленням (__method__
), які називаються методами dunder або магічними методами. Ми детальніше розглянемо ці методи в майбутньому. Наразі можна використовувати лише один із цих спеціальних методів: __init__
. Він ініціалізує примірник певними даними.
class Person:
"""Person class implementation"""
programming_language: str = "Python"
def __init__(
self, first_name: str, last_name: str, job_title: str
) -> None:
"""Initialize a person instance"""
self.first_name = first_name
self.last_name = last_name
self.job_title = job_title
def get_fullname(self) -> str:
"""Return a person's fullname"""
return " ".join([self.first_name, self.last_name])
serhii = Person("Serhii", "Horodilov", "Software Engineer")
vlad = Person("Vladyslav", "Ponomaryov", "Release Manager")
serhii.first_name # Serhii
serhii.last_name # Horodilov
Зверніть увагу, що це визначення виклику має властивість під назвою programming_language
, визначену за межами методу __init__
. Ця властивість є спільною для всіх екземплярів класу.
Дещо Більше про self
self
- це не що інше, як конвенція. Методи екземпляра отримають вказівник на сам екземпляр як перший аргумент. У двох словах: це фактичний об’єкт для виклику методу. Наприклад, Клас студента визначає атрибути (ім’я студента та бали) і методи, доступні для кожного екземпляра студента: виконайте завдання або пропустіть заняття. Тоді як фактичний екземпляр студента містить дані та методи, пов’язані з одним студентом. self
є посиланням саме на цей об’єкт.
Приховання Даних
У багатьох мовах програмування реалізовані модифікатори доступу. Python також має.

«Приватні» змінні екземплярів, до яких можна отримати доступ лише зсередини об’єкта, не існують у Python [docc]. Це реалізовано на рівні домовленності.
Ім’я з префіксом підкреслення (наприклад, _spam
) слід розглядати як закриту частину API (незалежно від того, чи це функція, метод або елемент даних). Вони не повинні використовуватися поза межами самого класу та можуть бути змінені без попередження.
Оскільки існує дійсний варіант використання для приватних членів класу (а саме, щоб уникнути зіткнень імен з іменами, визначеними підкласами), існує обмежена підтримка такого механізму, що називається викривлення імен. Будь-який ідентифікатор із принаймні двома символами підкреслення на початку (наприклад, __spam
) текстово замінюється на _classname__spam
, де _classname
є поточною назвою класу з видаленням підкреслення на початку.
class Employee:
"""Employee superclass example"""
first_name: str = ""
last_name: str = ""
_rate: int = 0
__tax: float = 0.18
def _get_amount(self, hours: int) -> int:
return self._rate * hours
def _get_tax(self, amount: int) -> int:
return int(round(self.__tax * amount, 0))
def get_balance(self, hours: int) -> int:
amount = self._get_amount(hours)
tax = self._get_tax(amount)
return amount - tax
def set_rate(self, rate: int) -> None:
self._rate = rate
class Employee10PercentTax(Employee):
_Employee__tax = 0.10
Кілька Слів про Наслідування
Примітка
Всього в двох словах. Ця тема розкривається в наступних статтях.
Ви можете отримати свої класи від суперкласу. Похідні класи називаються підкласами, а клас, який використовується для успадкування, називається суперкласом. Іншими термінами є дочірній клас і батьківський клас, але вони не є поширеними ( це особиста думка автора).
Просто помістіть суперклас у дужки, які успадковують від нього два:
class Dog():
"""Abstract dog implementation"""
class JackRussellTerrier(Dog):
"""Jack russell terrier species implementation"""
Кілька Слів про Поліморфізм
Ви вже використовували це. Найпростішим поясненням є оператор додавання. Для різних типів даних він створюватиме різні типи виводу:
["a", "b", "c"] + ["d"] # the result is ["a", "b", "c", "d"]
"a" + "b" + "cd" # the result is "abcd"
Наприклад, у вас можуть бути різні класи, успадковані від базового класу, який забезпечує загальний інтерфейс, але кожен похідний клас може реалізовувати метод по-своєму.
class Animal:
"""Abstract animal"""
def voice(self):
pass
class Cat(Animal):
def voice(self):
print("MEOW")
class Dog(Animal):
def voice(self):
print("ARF)