Python
100 питань
Як створити віртуальне середовище?
•python -m venv venv.
•Активація Windows: venv\Scripts\activate.
•Linux/Mac: source venv/bin/activate.
•Деактивація: deactivate.
•pip install package.
Чим відрізняються списки, кортежі, множини?
•Список list — змінюваний: [1,2,3].
•Кортеж tuple — незмінюваний: (1,2,3).
•Множина set — без дублікатів: {1,2,3}.
•Словник dict — ключ-значення.
•Кортежі хешуються.
Що таке декоратори?
•Функція, яка модифікує іншу функцію.
•@decorator над визначенням.
•def log(f): def wrapper(*a): return f(*a); return wrapper.
•functools.wraps зберігає ім’я/докстрінг.
•Приклади: @property, @staticmethod.
Як працювати з файлами?
•with open('file.txt', 'r', encoding='utf-8') as f:.
•f.read() або for line in f:.
•Режими: r, w, a, rb.
•with автоматично закриває файл.
•pathlib.Path — сучасний підхід.
Що таке генератори?
•Функція з yield.
•Повертає ітератор.
•Лінивий обчислювальний процес (економить пам’ять).
•next(gen) — отримати наступний елемент.
•Генераторне вираження: (x*2 for x in range(10)).
Як встановити Python і перевірити, що він працює?
•Скачайте з python.org або встановіть через менеджер пакетів.
•Перевірте: python --version (або python3 --version).
•Перевірте pip: python -m pip --version.
•Оновіть pip: python -m pip install -U pip.
•Запустіть REPL: python.
Чим відрізняються python і python3 у Linux?
•У деяких дистрибутивах python = Python 2 (історично) або відсутній.
•python3 завжди вказує на Python
3.
•Для скриптів краще використовувати shebang: #!/usr/bin/env python3.
•pip/pip3 аналогічно.
•Віртуальні середовища вирішують конфлікти версій.
Як правильно встановлювати залежності в проекті?
•Створіть venv.
•Встановлюйте пакети через python -m pip install ....
•Зафіксуйте залежності: pip freeze > requirements.txt.
•На іншому ПК: pip install -r requirements.txt.
•Для великих проектів розгляньте Poetry/uv.
Що таке PEP 8 і навіщо він потрібен?
•PEP 8 — стиль коду Python.
•Робить код читабельним і єдиним у команді.
•Відступи: 4 пробіли.
•Імена: snake_case для функцій/змінних, PascalCase для класів.
•Автоформатери: black, лінтери: ruff.
Як працює імпорт модулів (import) у Python?
•import шукає модуль у sys.path.
•Локальна папка проекту зазвичай на початку sys.path.
•Файл __init__.py робить папку пакетом (у старих версіях обов’язково).
•Відносні імпорти: from .sub import x.
•Уникайте циклічних імпортів.
Чим відрізняється shallow copy від deep copy?
•Shallow copy копіює лише верхній рівень контейнера.
•Вкладені об’єкти залишаються спільними.
•Deep copy рекурсивно копіює все.
•Shallow: list.copy(), copy.copy().
•Deep: copy.deepcopy() (може бути дорогим).
Коли використовувати list, а коли tuple?
•list — якщо потрібно змінювати вміст.
•tuple — якщо дані мають бути незмінними.
•tuple можна використовувати як ключ dict (якщо елементи хешовані).
•tuple зазвичай трохи компактніше.
•Для повернення “пакетів” значень зручно використовувати tuple.
Як влаштовані словники dict і які операції швидкі?
•dict — хеш-таблиця.
•Доступ/вставка/видалення за ключем зазвичай O(1).
•Ключ має бути хешованим (immutable).
•Порядок вставки зберігається (Python 3.7+ гарантує).
•Для підрахунку використовуйте collections.Counter.
Як красиво формувати рядки (f-string)?
•f'Привіт, {name}'.
•Формат: f'{value:.2f}' для float.
•Дати: f'{dt:%Y-%m-%d}'.
•Ширина: f'{n:>10}'.
•Для відлагодження: f'{var=}' (3.8+).
Як працює розпаковка *args і **kwargs?
•*args — позиційні аргументи у кортеж.
•**kwargs — іменовані аргументи у dict.
•Можна проксувати виклик: f(*args, **kwargs).
•Розпаковка колекцій: [*a, *b].
•Розпаковка dict: {**d1, **d2}.
Що таке list comprehension і коли його використовувати?
•Короткий синтаксис створення списку.
•Приклад: [x*x for x in range(
•if x % 2 == 0].
•Читається краще, ніж ручний цикл (якщо вираз простий).
•Для генератора використовуйте (...).
•Для вкладених циклів — акуратно, не ускладнюйте.
Чим відрізняється generator expression від list comprehension?
•List comprehension створює список одразу.
•Generator expression створює елементи ліниво.
•Генератор економить пам’ять на великих даних.
•Приклад: sum(x*x for x in data).
•Генератор можна «вичерпати» один раз.
Як працює enumerate і чому він зручний?
•enumerate(iterable) дає (індекс, значення).
•Приклад: for i, item in enumerate(items, start=1): ...
•Позбавляє від ручного лічильника.
•Працює з будь-яким ітератором.
•Покращує читабельність.
Як правильно сортувати списки (sorted vs sort)?
•list.sort() сортує на місці і повертає None.
•sorted(iterable) повертає новий список.
•key= — функція ключа: sorted(users, key=lambda u: u.age).
•reverse=True — зворотній порядок.
•Стабільне сортування (важливо для багаторівневого).
Як об’єднувати та фільтрувати колекції (map/filter) і коли краще comprehension?
•map/filter повертають ітератори.
•Приклад: map(str, nums).
•filter(fn, items) залишає елементи, де fn=True.
•Comprehension часто читається простіше.
•Для складної логіки краще звичайний цикл.
Як влаштована обробка виключень try/except/else/finally?
•try — код, який може впасти.
•except ловить конкретні виключення (не ловіть голий except).
•else виконується, якщо виключення не було.
•finally виконується завжди (очистка).
•raise для пробросу/створення помилки.
Як створити власне виключення?
•Наслідуйся від Exception: class MyError(Exception): pass.
•Використовуй осмислене ім’я.
•Передавай повідомлення: raise MyError('...').
•Для параметрів — зберігай їх у атрибутах.
•Не наслідуйся від BaseException.
Що таке контекстний менеджер і with?
•with гарантує звільнення ресурсу.
•Файли, блокування, з’єднання.
•Свій менеджер: реалізуй __enter__ і __exit__.
•Або використовуй contextlib.contextmanager.
•Спрощує безпечний код.
Як працювати з датою і часом (datetime)?
•datetime.datetime.now() — поточне локальне.
•Краще зберігати UTC: datetime.datetime.now(datetime.timezone.utc).
•Парсинг: datetime.datetime.fromisoformat(...).
•Формат: dt.strftime('%Y-%m-%d').
•Різниця: timedelta.
Як безпечно працювати з шляхами (pathlib)?
•from pathlib import Path.
•p = Path('data') / 'file.txt'.
•p.exists(), p.is_file(), p.read_text(encoding='utf-8').
•Створити папку: p.parent.mkdir(parents=True, exist_ok=True).
•Кросплатформенно і читабельно.
Як читати/писати JSON?
•імпортуй json.
•json.loads(text) → dict/list.
•json.dumps(obj, ensure_ascii=False) → рядок.
•Для файлів: json.load(fp), json.dump(obj, fp).
•Для datetime роби перетворення (наприклад, ISO рядок).
Що таке dataclass і навіщо він потрібен?
•dataclass зменшує boilerplate для класів даних.
•@dataclass автоматично створює __init__/__repr__/__eq__.
•Можна робити frozen=True (незмінність).
•default_factory для списків/словників.
•Зручно для DTO/моделей.
Як зробити незмінний об’єкт у Python?
•Використовуй dataclass(frozen=True).
•Або NamedTuple / typing.NamedTuple.
•Для колекцій: tuple замість list, frozenset замість set.
•Не мутуй внутрішні структури.
•Для конфігів це зменшує баги.
Що таке @property і коли його використовувати?
•Робить метод схожим на поле.
•Дозволяє обчислювані властивості.
•Можна додати валідацію в setter.
•Допомагає приховувати внутрішнє представлення.
•Не зловживай — складність теж зростає.
Як працює наслідування і super()?
•class Child(Parent): ...
•super() викликає методи базового класу за MRO.
•В multiple inheritance MRO критичний.
•Завжди використовуй super() у кооперативних класах.
•Перевір MRO: Class.mro().
Що таке MRO і чому воно важливе?
•MRO — порядок пошуку методів при наслідуванні.
•Використовується алгоритм C3 linearization.
•Впливає на super() у множинному наслідуванні.
•Помилки MRO → TypeError при створенні класу.
•Дивись Class.__mro__ / Class.mro().
Що таке dunder методи (__str__, __repr__, __iter__)?
•Це протоколи поведінки об’єктів.
•__repr__ — для розробника, __str__ — для користувача.
•__len__ робить об’єкт сумісним із len().
•__iter__/__next__ — ітератор.
•__enter__/__exit__ — контекстний менеджер.
Як правильно реалізувати __repr__?
•Робіть однозначне представлення.
•Ідеально: щоб можна було відновити об’єкт (якщо реально).
•Використовуй f'ClassName(x={self.x!r})'.
•Не робіть важких обчислень.
•Для dataclass __repr__ генерується автоматично.
Що таке ітератор і ітерований об’єкт?
•Ітерований — те, по чому можна пройти for.
•Ітератор — об’єкт з __iter__ і __next__.
•iter(obj) повертає ітератор.
•next(it) дає наступний елемент або StopIteration.
•Генератори — ітератори.
Як використовувати itertools для ефективних циклів?
•itertools.chain об’єднує послідовності.
•itertools.islice робить “зріз” ітератора.
•itertools.groupby групує (на відсортованих даних).
•itertools.product для декартового добутку.
•Добре для великих потоків даних.
Чим відрізняються * і / у сигнатурі функції (keyword-only і positional-only)?
•f(a, /, b) — позиційний тільки a.
•f(*, x, y) — x і y тільки іменовані.
•Зменшує помилки при виклику.
•Допомагає підтримувати API.
•Часто використовується в бібліотечному коді.
Що таке typing і навіщо потрібні type hints?
•Type hints — підказки типів (не обов’язкові для інтерпретатора).
•Покращують автодоповнення IDE.
•Допомагають статичним аналізаторам (mypy/pyright).
•Документують API.
•Знижують кількість багів у великих проектах.
Як використовувати Optional, Union і | (PEP 604)?
•Optional[str] = Union[str, None].
•У 3.10+: str | None.
•Union[int, str] = int | str.
•Віддавайте перевагу | у сучасному коді.
•Не забувайте обробляти None.
Що таке Protocol і коли він корисний?
•Protocol описує “утиний тип” за методами.
•Дозволяє типізувати інтерфейси без наслідування.
•Приклад: об’єкт з методом .read().
•Корисно для моків і абстракцій.
•Потрібен typing.Protocol (з 3.8+) або typing_extensions.
Як правильно логувати (logging) замість print?
•import logging; log = logging.getLogger(__name__).
•Використовуй рівні: debug/info/warning/error.
•Налаштуй формат і handler.
•Не логуй секрети (токени/паролі).
•У бібліотеці не конфігуруй root-logger.
Як читати великі файли без завантаження в пам’ять?
•Ітеруй по рядках: for line in f:.
•Для бінарних — читай чанками: f.read(8192).
•Використовуй генератори для пайплайна.
•Не роби f.read() на гігабайтах.
•Для CSV — csv.reader по рядках.
Як працювати з CSV?
•import csv.
•reader = csv.DictReader(f).
•Пиши: csv.DictWriter(...).writeheader(); writer.writerow(...).
•Вказуй newline='' при open.
•Для кодувань використовуй encoding='utf-8'.
Як швидко шукати мінімум/максимум за ключем?
•min(items, key=...).
•max(items, key=...).
•key може бути lambda або attrgetter.
•Для словника: max(d, key=d.get).
•Це більш читабельно, ніж ручні цикли.
Як використовувати collections.Counter і defaultdict?
•Counter рахує частоти: Counter(words).
•most_common(n) — топ-N.
•defaultdict(list) зручно для групування.
•defaultdict(int) — лічильник без if.
•Покращує читабельність і швидкість написання коду.
Як групувати елементи списку за ключем?
•Для невеликих даних: defaultdict(list).
•group[key].append(item).
•Для groupby потрібно попередньо відсортувати за ключем.
•key-функція має бути стабільною.
•Результат зазвичай dict[key] -> list[items].
Як зробити HTTP-запити в Python?
•Популярно: requests (якщо доступний).
•У стандартній бібліотеці: urllib.request (менш зручний).
•Для async: httpx або aiohttp.
•Завжди ставте таймаут.
•Перевіряйте статус і обробляйте помилки.
Як безпечно парсити користувацький ввід?
•Явно приводити типи: int(x), float(x) з try/except.
•Перевіряти діапазони і формат.
•Не використовувати eval/exec для вхідних даних.
•Для JSON використовувати json.loads.
•Для шляхів — pathlib і whitelisting.
Що таке f-string і чому він краще format?
•f-string швидше і читабельніше.
•Підтримує вирази всередині {}.
•Зручне форматування чисел/дат.
•Легше підтримувати, ніж конкатенація.
•format корисний, коли шаблон зберігається окремо.
Як зробити CLI-скрипт на Python?
•Вхідна точка: if __name__ == '__main__': main().
•Парсинг аргументів: argparse.
•Повернення коду: sys.exit(code).
•Логи замість print у складних утилітах.
•Вкажіть shebang для Linux.
Як використовувати argparse для аргументів командного рядка?
•parser = argparse.ArgumentParser().
•parser.add_argument('--path', required=True).
•args = parser.parse_args().
•Підтримка subcommands: add_subparsers().
•Автоматична генерація help.
Що таке asyncio і коли воно потрібно?
•asyncio — конкурентність для I/O (мережа/файли) без потоків.
•Використовуй async def і await.
•Не прискорює CPU-інтенсивні задачі.
•Підходить для web-сервісів/ботів/парсерів.
•Для CPU — multiprocessing.
У чому різниця між threading і multiprocessing?
•threading — потоки в одному процесі, спільний GIL.
•Добре для I/O задач.
•multiprocessing — окремі процеси, паралелить CPU.
•IPC і серіалізація дорожчі.
•Вибір залежить від профілю навантаження.
Що таке GIL і як він впливає на продуктивність?
•GIL обмежує виконання байткоду Python одним потоком.
•CPU-інтенсивні задачі не масштабуються потоками.
•I/O задачі зазвичай працюють нормально з потоками.
•Для CPU — multiprocessing або NumPy (C-код).
•Альтернатива: PyPy, Cython, Rust/Go розширення.
Як запустити кілька async задач паралельно?
•Створи задачі: asyncio.create_task(coro()).
•Збери: await asyncio.gather(*tasks).
•Для обмеження паралелізму використовуй Semaphore.
•Обробляй виключення (return_exceptions).
•Не забувай про таймаути.
Як правильно робити таймаути в asyncio?
•asyncio.wait_for(coro, timeout=...).
•В Python 3.11+: asyncio.timeout().
•На мережевих клієнтах ставте таймаути на рівні бібліотеки.
•Лови asyncio.TimeoutError.
•Робіть retry з backoff при необхідності.
Як писати тести: unittest або pytest?
•unittest — стандартна бібліотека, більш «Java-стиль».
•pytest — простий синтаксис, потужні фікстури.
•В CI зручно запускати pytest.
•Структуруй тести за модулями/фічами.
•Ізолюй зовнішні залежності за допомогою моків.
Як мокати залежності в тестах?
•Використовуй unittest.mock (patch, MagicMock).
•Мокай на місці використання, а не визначення.
•Віддавай перевагу dependency injection там, де можливо.
•Перевіряй виклики: assert_called_once_with.
•Не перетворюй тест у копію реалізації.
Як працювати з фікстурами в pytest?
•@pytest.fixture для підготовки даних.
•scope=function/module/session.
•fixture може повертати об’єкт або yield для teardown.
•Фікстури можна параметризувати.
•Це зменшує дублювання тестів.
Як вимірювати покриття тестами?
•coverage.py або pytest-cov.
•Запуск: pytest --cov=package.
•Дивись звіт HTML.
•Високе покриття не гарантує якість, але допомагає.
•Мета: покривати критичну бізнес-логіку.
Як профілювати Python-код?
•cProfile для загального профілю.
•timeit для мікробенчмарків.
•line_profiler для построчного аналізу.
•py-spy для продакшена без впровадження.
•Спочатку вимірюй, потім оптимізуй.
Що таке генератори контексту (contextlib.contextmanager)?
•Дозволяє писати with через генератор.
•@contextmanager над функцією.
•yield розділяє enter/exit.
•У finally роби cleanup.
•Зручно для тимчасових налаштувань/ресурсів.
Як кешувати обчислення (functools.lru_cache)?
•@lru_cache(maxsize=...).
•Працює для чистих функцій.
•Аргументи мають бути хешованими.
•cache_clear() очищає.
•Для складних кейсів — зовнішній кеш (Redis).
Як використовувати @dataclass з default_factory?
•Для mutable значень не можна робити default=[].
•Робіть field(default_factory=list).
•Аналогічно для dict/set.
•Це запобігає спільному списку для всіх екземплярів.
•Часті помилки новачків.
Чому небезпечно писати def f(x, arr=[])?
•Значення за замовчуванням обчислюється один раз при визначенні функції.
•Список буде спільним між викликами.
•Правильно: def f(x, arr=None): arr = arr or [].
•Те саме для dict/set.
•Це класична пастка Python.
Як обробляти конфігурацію проекту?
•Розділяй конфіг і код.
•Використовуй змінні оточення для секретів.
•Для .env можна використовувати python-dotenv.
•Валідируй конфіг (pydantic/settings).
•Не коміти секрети в git.
Як працювати з SQLite (sqlite3)?
•import sqlite3; conn = sqlite3.connect('db.sqlite').
•cursor.execute('SELECT ...', params).
•Використовуй параметризацію, не конкатенацію.
•conn.commit() для запису.
•conn.close() або менеджер контексту.
Що таке SQLAlchemy і навіщо він потрібен?
•ORM і SQL toolkit.
•Дозволяє писати запити через Python-вирази.
•Зручні міграції через Alembic.
•Добре для складних проектів.
•Для простого скрипта sqlite3 може вистачити.
Як правильно працювати з файлами у бінарному режимі?
•open(path, 'rb') для читання байт.
•Для запису: 'wb'.
•Не вказуй encoding у бінарному режимі.
•Для великих файлів — чанки.
•Для хешів — hashlib.
Як порахувати хеш файлу (sha256)?
•import hashlib.
•h = hashlib.sha256().
•Читай файл чанками і h.update(chunk).
•В кінці h.hexdigest().
•Не читай великий файл цілком.
Як працювати з регулярними виразами (re)?
•re.search/findall/sub.
•Компілюй шаблон: re.compile(pattern).
•Використовуй raw-рядки: r'\d+'.
•Флаги: re.I, re.M, re.S.
•Не ускладнюй regex, якщо можна простіше.
Як писати читабельний код: функції маленькі, імена зрозумілі?
•Однією функцією — одна відповідальність.
•Зрозумілі імена важливіше коментарів.
•Уникай “магічних” чисел — винеси в константи.
•Пиши docstring для публічного API.
•Рефакторюй, якщо стало важко читати.
Як користуватися лінтерами і форматтерами (ruff/black)?
•Black форматуватиме код автоматично.
•Ruff об'єднує лінт і правила.
•Налаштуй у pyproject.toml.
•Запусти в CI, щоб не ловити стиль руками.
•Не сперечайся зі стилем — автоматизуй.
Як влаштовані пакети і файли __init__.py?
•Пакет — папка з модулями.
•__init__.py може експортувати публічний API.
•Не роби важких імпортів у __init__.py.
•Уникай циклічних залежностей.
•Намагайся тримати структуру простою.
Як працювати з віртуальними оточеннями в IDE?
•Створи venv у корені проекту.
•Вибери інтерпретатор venv у налаштуваннях IDE.
•Встановлюй залежності у цей venv.
•Перевір, що термінал IDE також використовує venv.
•Не змішуй глобальні і проектні пакети.
Як упакувати проект (pyproject.toml) і зробити встановлення?
•Сучасний стандарт — pyproject.toml.
•Вкажи залежності і метадані.
•Використовуй Poetry/uv/pip-tools за вибором.
•Робіть версії і релізи усвідомлено.
•Публікація у PyPI — окремий крок (twine).
Як організувати структуру проекту для застосунку?
•Розділяй domain/logic і інфраструктуру (IO).
•Не змішуй API-шар і бізнес-логіку.
•Тримай залежності явними.
•Додай tests/ поруч із кодом або окремо.
•Винось конфіги в окремий модуль.
Як працювати з залежностями: requirements.txt vs poetry.lock?
•requirements.txt — простий список залежностей (pip).
•lock-файл фіксує точні версії.
•Poetry робить lock автоматично.
•Для продакшена важлива відтворюваність.
•Не оновлюй залежності без тестів.
Як читати змінні оточення в Python?
•import os.
•os.environ['KEY'] (упаде, якщо немає).
•os.getenv('KEY', default) безпечніше.
•Вказуй типи явно (int/bool).
•Для .env використовуй python-dotenv (у розробці).
Як безпечно працювати з секретами (API ключі)?
•Ніколи не зберігай ключі у репозиторії.
•Використовуй env vars/secret manager.
•Обмежуй права ключа (мінімальні).
•Ротуй ключі при витоках.
•Маскуй у логах і помилках.
Як обробляти HTTP-помилки і ретраї?
•Перевіряй статус відповіді і response.raise_for_status() (requests).
•Робіть таймаути.
•Робіть retry тільки для ідемпотентних запитів.
•Використовуй exponential backoff.
•Логуй причини невдачі.
Що таке контракти типів у рантаймі (pydantic)?
•Type hints самі по собі не валідовують дані.
•Pydantic валідовує вхідні дані в моделях.
•Зручно для API/конфігів.
•Генерує зрозумілі помилки.
•Не використовуй для “гарячого” шляху, де важлива кожна наносекунда.
Як серіалізувати dataclass у dict/JSON?
•dataclasses.asdict(obj) → dict.
•Потім json.dumps(dict).
•З datetime роби перетворення у рядок.
•Для вкладених об'єктів asdict працює рекурсивно.
•Для контролю формату використовуй pydantic або явний код.
Як правильно порівнювати рядки і враховувати регістр/локаль?
•Для простого: s.lower() або s.casefold().
•casefold краще для Unicode.
•Для локалі потрібна окрема обробка (locale).
•Не забудь strip() для вводу.
•Для пошуку використовуйте in/startswith/endswith.
Як працювати з кодуваннями і Unicode?
•Завжди вказуй encoding при роботі з текстовими файлами.
•Для терміналу/Windows іноді потрібні налаштування.
•Внутрішньо Python рядки — Unicode.
•Байти ↔ рядок: encode/decode.
•Проблеми вирішуй на межі (IO).
Як обробляти помилки вводу-виводу (IOError/OSError)?
•Лови конкретні виключення: FileNotFoundError, PermissionError.
•Перевіряй існування файлу при необхідності.
•Робіть атомарний запис (через temp файл).
•Логуй контекст (шлях, операція).
•Не приховуй помилки мовчки.
Як зробити атомарний запис файлу?
•Пиши у тимчасовий файл поруч.
•fsync за необхідності.
•Потім replace/rename на цільовий шлях (атомарно на більшості FS).
•Використовуй pathlib і os.replace.
•Це захищає від пошкоджених файлів при падінні.
Як влаштовані генератори виключень і ланцюжки raise from?
•raise NewError() from e зберігає причину.
•Це покращує діагностику.
•Без from причина губиться або стає неочевидною.
•Використовуй для обгортань над низькорівневими помилками.
•Можна подавити контекст: raise ... from None.
Як правильно писати docstring?
•Коротко: що робить функція.
•Опис аргументів і повертаного.
•Вкажи виключення, якщо важливо.
•Приклади використання допомагають.
•Дотримуйся одного стилю (Google/Numpy) у проекті.
Як працювати з датами у форматі ISO?
•Зберігай дати як рядок ISO 8601 або UTC timestamp.
•Парсинг: datetime.fromisoformat (для стандартного ISO).
•Форматування: dt.isoformat().
•Для timezone використовуй timezone-aware datetime.
•Не змішуй naive і aware datetime.
Що таке менеджер залежностей uv і чому він популярний?
•uv — швидкий менеджер пакетів/віртуальних оточень (на Rust).
•Швидко створює venv і встановлює пакети.
•Зручний у CI.
•Альтернатива pip/poetry для багатьох команд.
•Вибір інструменту залежить від процесів команди.
Як писати REST API на Python (коротко FastAPI)?
•FastAPI використовує type hints і pydantic.
•Описуй ендпоінти через @app.get/post.
•Моделі даних — через BaseModel.
•Запуск: uvicorn app:app --reload.
•Документація генерується автоматично (Swagger).
Чим відрізняється Flask від FastAPI?
•Flask — мінімалістичний, синхронний за замовчуванням.
•FastAPI — сучасний, async-дружній.
•FastAPI генерує OpenAPI за типами.
•У Flask більше ручної роботи з валідацією.
•Вибір залежить від вимог і звичок команди.
Як працювати з файловими завантаженнями у web (загальний підхід)?
•Обмежуй розмір завантаження.
•Перевіряй MIME/розширення (не довіряй тільки розширенню).
•Генеруй нове ім'я файлу.
•Зберігай поза публічною директорією, якщо потрібно.
•Логуй події та помилки.
Як уникнути витоків пам’яті у Python додатках?
•Не тримай глобальні колекції без контролю.
•Слідкуй за кешами і зростанням списків.
•Закривай файли/з’єднання.
•Для профілювання пам’яті використовуй tracemalloc/memory_profiler.
•Шукай цикли посилань і великі об’єкти.
Що таке weakref і коли він корисний?
•weakref зберігає слабке посилання, не утримуючи об’єкт.
•Корисно для кешів і спостерігачів.
•Коли об’єкт видаляється, weakref стає порожнім.
•Є WeakKeyDictionary/WeakValueDictionary.
•Використовуй обережно, щоб не отримати несподіваний None.
Як прискорювати “повільний” Python код без переписування всього?
•Спершу профілюй і знайди гарячі точки.
•Замінюй алгоритм/структури даних.
•Використовуй вбудовані функції (вони на C і швидше).
•Розглянь NumPy/пакети на C.
•Лише потім думай про Cython/розширення.
Як працювати з потоками даних (pipeline) через генератори?
•Створюй функції-генератори, які yield елементи.
•З'єднуй їх ланцюжком.
•Фільтрація/маппінг виконуються ліниво.
•Це економить пам'ять.
•Добре для обробки великих файлів/логів.
Як правильно закривати ресурси при помилках?
•Використовуй with/менеджери контексту.
•Для кількох ресурсів: with a() as x, b() as y:.
•У try/finally закривай те, що не підтримує with.
•Логуй виключення та контекст.
•Не залишай з'єднання/файли відкритими.
Як безпечно читати та оновлювати словник у багатопоточному середовищі?
•У CPython окремі операції з dict атомарні, але логіка з кількох кроків — ні.
•Використовуй threading.Lock навколо критичної секції.
•Для черг використовуй queue.Queue.
•Уникай спільного mutable стану.
•Для multiprocessing — Manager або процесні черги.
Які “must know” інструменти для Python-розробника?
•venv/pip (або uv/poetry) для оточення.
•ruff/black для стилю та лінтингу.
•pytest для тестів.
•mypy/pyright для типів (за бажанням).
•Git + CI для автоматичних перевірок.