← Java

Після цього уроку ви зможете

Конспект і таймкоди

0:00

`self` і область видимості

self — явний параметр instance method, через який код звертається до конкретного екземпляра класу. self.card означає атрибут цього екземпляра, тоді як локальна змінна card живе лише у своїй функції або блоці видимості.

Однакові назви технічно можливі, але збільшують когнітивне навантаження. Префікс self. одночасно потрібен Python для правильного доступу до instance attribute і показує читачеві, де зберігається стан.

Термін

self

Загальноприйнята назва першого параметра instance method. Python передає bound instance неявно під час виклику obj.method(), але ім’я self саме по собі не є keyword.

Практика

Відокремити local state від instance state

  1. Створи два PageObject instances із різними page values і доведи assertions, що зміна local variable не змінює self.page іншого instance.
  • Обидва instances мають незалежні page attributes.
  • У method немає global state.
  • Автор може пояснити, чому obj.method() передає obj як перший argument.
3:00

`__init__` задає обов’язковий стан об’єкта

Через __init__ клас отримує залежності й початковий стан, без яких його методи не мають сенсу. Наприклад, компонент приймає кореневий locator, а Page Object — Playwright page; наступні методи перевикористовують ці значення через self.

У повсякденній мові __init__ часто називають constructor. Технічно екземпляр створює __new__, а __init__ ініціалізує вже створений об’єкт. Для звичайного Page Object достатньо реалізувати саме __init__.

Уточнення

__init__ — initializer, не етап створення instance

У повсякденній мові __init__ часто називають constructor, але Python data model розділяє __new__, який створює instance, і __init__, який налаштовує вже створений instance.

Термін

__init__

Initializer, який викликається після створення instance методом __new__ і налаштовує його початковий стан; він не повинен повертати значення, відмінне від None.

Приклад коду

Instance state через self та __init__

class PageObject:
    def __init__(self, page: str):
        self.page = page

    def describe(self) -> str:
        return f"Page: {self.page}"


obj = PageObject("checkout")
assert obj.describe() == "Page: checkout"
print(obj.describe())

page є instance attribute: кожен PageObject отримує власний стан через __init__, а method читає його через self.

Очікуваний результат: Команда друкує Page: checkout і assertion проходить.

6:00

Що зберігає Playwright `page`

Playwright Page представляє окрему вкладку або сторінку в browser context. Переданий у Page Object екземпляр визначає, з яким саме браузерним контекстом працюватимуть locators, переходи й assertions.

Збереження page як self.page прибирає потребу передавати його в кожен метод. Залежність залишається явною в initializer, а всі дії конкретного Page Object використовують одну й ту саму вкладку.

8:16

Для чого потрібен `__init__.py`

Наявність __init__.py робить директорію звичайним Python package і може визначати його зручний публічний API через imports або __all__. Це допомагає IDE, імпортам і читачеві зрозуміти межу модуля.

Сучасний Python також підтримує namespace packages без __init__.py, тому файл не є абсолютною вимогою для кожної імпортованої директорії. У навчальному проєкті явний package зазвичай простіший і передбачуваніший.

Що змінилося після запису

__init__.py не є абсолютною вимогою

У відеоУ відео __init__.py пояснено як ознаку Python package і місце для публічних imports.

АктуальноДля regular package це коректна практична модель, але Python 3.3+ підтримує implicit namespace packages, де namespace directory навмисно не містить __init__.py.

Перевірено 2026-07-31

Термін

namespace package

Package, який може бути розподілений між кількома distributions. Native namespace packages доступні з Python 3.3 і не мають __init__.py у namespace directory.

Один underscore, наприклад _locator, — домовленість «внутрішня деталь, не використовуй без потреби». Інтерпретатор не забороняє доступ. Подвійний початковий underscore запускає name mangling, щоб зменшити випадкові конфлікти в нащадках, але теж не створює security boundary.

На відміну від private або protected у статично типізованих мовах, Python більше покладається на дисципліну автора й користувача класу. IDE може попередити про звернення до non-public member, але виконання зазвичай можливе.

Термін

non-public API

Python convention: name з одним leading underscore вважається implementation detail. Подвійний leading underscore запускає name mangling для уникнення конфліктів, але не гарантує privacy.

15:00

Коли приватний helper покращує код

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

Водночас Page Object має залишатися простим. Не варто ділити кожен рядок на helper: виділення виправдане, коли воно називає реальну дію або приховує поточну складність.

19:35

Інкапсуляція відкриває безпечний інтерфейс

Інкапсуляція поєднує стан і поведінку та визначає дозволений спосіб взаємодії з об’єктом. Практичний акцент — не «сховати все», а відкрити невеликий зрозумілий інтерфейс, який не змушує зовнішній код знати внутрішню послідовність дій.

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

23:01

Access modifiers і зближення мов

Java і C# формально перевіряють public, private та protected, тоді як Python використовує переважно conventions. Водночас суворіші мови скорочують boilerplate, а Python і JavaScript додають type hints та інструменти статичного аналізу.

Python annotations допомагають IDE й type checker, але самі по собі не перетворюють Python на статично типізовану мову та не гарантують runtime-перевірку. Їхня користь — ранній зворотний зв’язок і краща навігація по API.

25:36

Як вивчати ООП послідовно

Абстрактні принципи стають зрозумілішими після практики: спочатку помітити code smells, потім розібрати базові механізми ООП, далі — patterns і SOLID. KISS, DRY та YAGNI варто застосовувати паралельно як питання до конкретного коду, а не як привід будувати структуру наперед.

Найкраща перевірка розуміння — пояснити, який публічний контракт має клас, який стан йому справді потрібен і яку поточну проблему вирішує кожен виділений метод.

26:20

Термін виконання практики

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

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