RecallDeck
Направление

Подготовка к собеседованию — Python-разработчик

Колода из 522+ карточек с вопросами для собеседования по направлению «Python-разработчик» — по темам и уровню сложности, с возвратом ровно перед тем, как вы забудете. Посмотрите несколько карточек ниже, затем войдите, чтобы учить всё направление по расписанию в стиле Anki (SM-2).

522 карточки15 тем

Бесплатно · вход через GitHub · ваш прогресс остаётся с вами.

Что внутри

Все темы направления, сгруппированные так, как вы будете их учить.

Python

130 карточек
Ядро языкаМодель данных и внутренностиКонкурентность и asyncStdlib, типизация и тесты

Базы данных

104 карточки
Основы SQLВнутренности Postgres и оптимизацияNoSQL и Redis

Бэкенд

175 карточек
HTTP и REST APIАрхитектура и масштабированиеАутентификация и безопасностьDjango и FastAPIORM и SQLAlchemy

Основы CS

43 карточки
Структуры данных и алгоритмы

DevOps и инфраструктура

35 карточек
Docker, CI/CD и Linux

Поведенческое интервью

35 карточек
Поведенческое интервью

Примеры вопросов

Несколько карточек из колоды — откройте ответ, затем войдите, чтобы учить весь набор по расписанию.

Чем отличаются изменяемые (mutable) и неизменяемые (immutable) типы?

Короткий ответ: Изменяемые объекты можно менять «на месте» без создания нового объекта (list, dict, set, bytearray), неизменяемые — нет (int, float, str, bytes, tuple, frozenset, bool, None). Любое «изменение» неизменяемого создаёт новый объект.

Подробно: Изменяемость — это про то, может ли объект поменять своё содержимое, сохранив тот же id() (адрес в памяти).

# Неизменяемый: операция создаёт НОВЫЙ объект
s = "hello"
print(id(s))
s += " world"      # создаётся новая строка
print(id(s))       # id поменялся — это другой объект

# Изменяемый: меняется тот же объект
lst = [1, 2, 3]
print(id(lst))
lst.append(4)      # меняем на месте
print(id(lst))     # id тот же

Почему это важно:

  • Хешируемость. Только неизменяемые (по содержимому) объекты можно класть в dict-ключи и set. Если бы ключ менялся, его хеш «уехал» бы, и его нельзя было бы найти.
  • Безопасность при шаринге. Неизменяемый объект можно безопасно расшарить между потоками/функциями — никто его не испортит.
  • Аргументы функций. Передача изменяемого объекта означает, что функция может его поменять (см. вопрос про передачу аргументов).

⚠️ Ловушка: tuple неизменяем, но если в нём лежит list, этот список можно поменять:

t = ([1, 2], 3)
t[0].append(99)   # OK! список внутри мутабелен
print(t)          # ([1, 2, 99], 3)
# t[0] = [...]    # вот ЭТО — TypeError, переприсвоить элемент нельзя

А ещё hash(([1,2], 3)) упадёт — кортеж нехешируем, если внутри есть нехешируемый элемент.

Что делает SELECT и в каком порядке выполняются части запроса?

Короткий ответ: SELECT извлекает строки из таблиц. Логический порядок выполнения НЕ совпадает с порядком написания: сначала FROM, затем WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, LIMIT.

Подробно:

Порядок написания (синтаксический):

SELECT   DISTINCT col1, agg(col2)
FROM     t
WHERE    cond
GROUP BY col1
HAVING   agg_cond
ORDER BY col1
LIMIT    10 OFFSET 20;

Логический порядок исполнения:

1. FROM / JOIN      -- какие таблицы, как соединить
2. WHERE            -- фильтр строк ДО группировки
3. GROUP BY         -- группировка
4. HAVING           -- фильтр групп ПОСЛЕ агрегации
5. SELECT           -- вычисление выражений, алиасов
6. DISTINCT         -- удаление дублей
7. ORDER BY         -- сортировка
8. LIMIT / OFFSET   -- срез

⚠️ Ловушка: алиас из SELECT нельзя использовать в WHERE (т.к. WHERE выполняется раньше SELECT), но можно в ORDER BY и часто в GROUP BY (зависит от СУБД). Пример ошибки:

SELECT salary * 12 AS annual FROM emp WHERE annual > 100000; -- ОШИБКА
SELECT salary * 12 AS annual FROM emp ORDER BY annual;        -- ОК
  1. Что такое HTTP и как устроен цикл запрос-ответ?

Короткий ответ: HTTP (HyperText Transfer Protocol) — текстовый прикладной протокол клиент-сервер поверх TCP (в HTTP/3 — поверх QUIC/UDP). Клиент отправляет запрос, сервер возвращает ответ; соединение без сохранения состояния между запросами (stateless).

Подробно:

Запрос состоит из стартовой строки (метод + путь + версия), заголовков и опционального тела:

POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
Content-Length: 38

{"name": "Анна", "email": "a@ex.com"}

Ответ состоит из строки статуса (версия + код + reason phrase), заголовков и тела:

HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/users/42

{"id": 42, "name": "Анна", "email": "a@ex.com"}

⚠️ Ловушка: «HTTP работает только поверх TCP» — неверно для HTTP/3, который использует QUIC поверх UDP. И reason phrase («OK», «Created») носит чисто информативный характер — клиенты должны опираться на числовой код, а не на текст.

Что такое Big O нотация?

Короткий ответ: Big O описывает, как растёт время работы или потребление памяти алгоритма при увеличении размера входных данных n, отбрасывая константы и младшие члены. Это верхняя оценка скорости роста.

Подробно:

Big O отвечает на вопрос «что произойдёт, когда n станет очень большим?». Нас не интересует точное число операций, а только характер роста. Поэтому O(2n + 100) упрощается до O(n), а O(3n² + n) — до O(n²).

Основные классы роста (от лучшего к худшему):

# O(1) — константа: не зависит от n
def first(arr):
    return arr[0] if arr else None

# O(log n) — логарифм: каждый шаг делит задачу пополам (бинарный поиск)
def binary_search(arr, target):
    lo, hi = 0, len(arr) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

# O(n) — линейная: один проход
def total(arr):
    s = 0
    for x in arr:        # n итераций
        s += x
    return s

# O(n log n) — эффективные сортировки (merge, quick, Timsort)
def sort_it(arr):
    return sorted(arr)

# O(n^2) — квадрат: вложенный цикл
def has_dup_naive(arr):
    for i in range(len(arr)):
        for j in range(i + 1, len(arr)):
            if arr[i] == arr[j]:
                return True
    return False

# O(2^n) — экспонента: наивный Фибоначчи, перебор подмножеств
def fib_naive(n):
    if n < 2:
        return n
    return fib_naive(n - 1) + fib_naive(n - 2)

Ориентир по росту при n = 1 000 000: O(1) — 1 операция, O(log n) — ~20, O(n) — миллион, O(n log n) — ~20 млн, O(n²) — триллион (уже слишком), O(2^n) — нереально даже при n = 50.

⚠️ Ловушка: Big O — это про асимптотику (поведение при больших n), а не про реальное время. O(n) алгоритм может быть медленнее O(n²) на маленьких данных из-за больших констант. Также путают: Big O (верхняя граница, Ω — нижняя, Θ — точная), в собесах под «O» обычно подразумевают Θ.

Что такое Docker и какую проблему он решает?

Короткий ответ: Docker — это платформа контейнеризации, которая упаковывает приложение вместе со всеми его зависимостями, библиотеками и конфигурацией в изолированный, переносимый образ. Решает проблему «у меня на машине работает, а на сервере нет».

Подробно:

Классическая боль: разработчик написал код на своём ноутбуке (Python 3.11, конкретная версия libpq, переменные окружения), а на сервере другая версия ОС, других библиотек нет, переменные не выставлены — приложение падает. Docker фиксирует всё окружение в образе, и этот образ одинаково запускается локально, в CI и на проде.

Что даёт Docker:

  • Воспроизводимость — один и тот же образ везде. Окружение описано кодом (Dockerfile), его можно версионировать в git.
  • Изоляция — контейнеры не мешают друг другу (зависимости, порты, процессы).
  • Переносимость — образ работает на любой машине с Docker, независимо от хостовой ОС.
  • Быстрый старт — контейнер поднимается за секунды (в отличие от VM).
# Собрать образ из Dockerfile в текущей директории
docker build -t myapp:1.0 .

# Запустить контейнер из образа, пробросить порт, в фоне
docker run -d -p 8000:8000 --name myapp myapp:1.0

# Посмотреть запущенные контейнеры
docker ps

# Зайти внутрь работающего контейнера
docker exec -it myapp bash

# Логи контейнера
docker logs -f myapp

⚠️ Ловушка: Docker не «виртуализирует железо» и не запускает полноценную ОС. Контейнеры используют ядро хоста. Поэтому Linux-образ нативно не запустится на ядре Windows — на Windows/macOS под капотом работает лёгкая Linux-VM (через WSL2 или гипервизор), и уже в ней крутятся контейнеры.

Чем отличается list от tuple?

Короткий ответ: list изменяемый, tuple — нет. tuple хешируем (если все элементы хешируемы), занимает меньше памяти, чуть быстрее создаётся. list используют для однородных изменяемых коллекций, tuple — для фиксированных гетерогенных записей.

Подробно:

Признак list tuple
Изменяемость да нет
Хешируемость нет да (если элементы хешируемы)
Память больше (есть запас под рост) меньше
Создание медленнее быстрее (литерал может кешироваться)
Семантика коллекция однородных элементов запись фиксированной структуры
import sys
print(sys.getsizeof([1, 2, 3]))   # ~88 байт
print(sys.getsizeof((1, 2, 3)))   # ~64 байта

Почему list больше: он держит переаллокацию (over-allocation) — заранее выделяет место под будущие append, чтобы амортизировать стоимость роста до O(1). tuple фиксирован, ему запас не нужен.

Когда что выбирать:

  • tuple — когда количество и смысл элементов фиксированы: координаты (x, y), возврат нескольких значений из функции, ключ словаря.
  • list — когда коллекция растёт/меняется/сортируется.

⚠️ Ловушка: «tuple быстрее» — правда лишь для создания литерала и доступа, но не магически во всём. И помни про вложенный мутабельный объект: tuple гарантирует неизменность ссылок, а не объектов, на которые они указывают.

Готовы закрепить навсегда?

Первая сессия — меньше минуты. Ваше будущее «я» на собеседовании скажет спасибо.

Вопросы об этом направлении

Как готовиться к собеседованию на «Python-разработчик»?

Учите концепции, которые придётся объяснять, а не только те, что умеете кодить. Направление «Python-разработчик» в RecallDeck даёт 522+ отобранных вопросов и возвращает каждый по расписанию в стиле Anki (SM-2) ровно перед тем, как вы забудете — чтобы на собеседовании ответы были под рукой.

Какие темы охватывает направление «Python-разработчик»?

Направление «Python-разработчик» разбито на ключевые области, которые реально проверяют на таких собеседованиях, — по темам и уровню сложности (Concept, Junior, Middle, Senior). Полный план и примеры вопросов можно посмотреть выше до входа.

Помогает ли интервальное повторение в подготовке к «Python-разработчик»?

Да. Активно вспоминать ответ и честно себя оценивать — куда прочнее для памяти, чем перечитывать заметки. RecallDeck планирует каждую карту «Python-разработчик» так, чтобы она вернулась перед моментом забывания: ежедневных повторений становится меньше, а знания держатся.

Направление «Python-разработчик» бесплатное?

Да — направление «Python-разработчик» и полный планировщик SM-2 бесплатны, с 20 новыми картами в день. Войдите через GitHub, и прогресс синхронизируется с аккаунтом. RecallDeck Pro ($5/мес или $29/год) поднимает дневной лимит и добавляет блиц-режим.

Другие направления

RecallDeckПодготовка к собеседованию на интервальных повторениях