Python вопросы с собеседований
Вопросы с собеседований по Python @workakkk - админ @machinelearning_interview - вопросы с собесдований по Ml @pro_python_code - Python @data_analysis_ml - анализ данных на Python @itchannels_telegram - 🔥 главное в ит РКН: clck.ru/3FmrFd
Больше📈 Аналитический обзор Telegram-канала Python вопросы с собеседований
Канал Python вопросы с собеседований (@python_job_interview) языкового сегмента Русский является активным участником. Сейчас сообщество объединяет 24 966 подписчиков, занимая 5 488 место в категории Технологии и приложения и 26 804 место в регионе Россия.
📊 Показатели аудитории и динамика
С момента создания невідомо проект демонстрирует стремительный рост, собрав аудиторию из 24 966 подписчиков.
Согласно последним данным от 05 июня, 2026, канал показывает стабильную активность. За последние 30 дней изменение числа участников составило -153, а за последние 24 часа — -5, при этом общий охват остаётся высоким.
- Статус верификации: Не верифицирован
- Уровень вовлечённости (ER): Средний показатель вовлечённости аудитории составляет 6.12%. В первые 24 часа после публикации контент обычно набирает 3.05% реакций от общего числа подписчиков.
- Охват публикаций: В среднем каждый пост получает 1 527 просмотров. В течение первых суток публикация набирает 762 просмотров.
- Реакции и взаимодействия: Аудитория активно поддерживает контент: среднее количество реакций на один пост — 8.
- Тематические интересы: Контент сосредоточен на ключевых темах, таких как github, api, собеседование, git, docker.
📝 Описание и контентная политика
Автор описывает ресурс как площадку для выражения субъективного мнения:
“Вопросы с собеседований по Python
@workakkk - админ
@machinelearning_interview - вопросы с собесдований по Ml
@pro_python_code - Python
@data_analysis_ml - анализ данных на Python
@itchannels_telegram - 🔥 главное в ит
РКН: clck.ru/3FmrFd”
Благодаря высокой частоте обновлений (последние данные получены 06 июня, 2026) канал поддерживает актуальность и высокий уровень охвата публикаций. Аналитика показывает, что аудитория активно взаимодействует с контентом, что делает его важной точкой влияния в категории Технологии и приложения.
actions = [
("Alice", "picked"),
("Bob", "looked"),
("Charlie", "picked"),
("Bob", "dropped"),
("Alice", "dropped"),
("Charlie", "ate")
]
Каждое действие — это кортеж: (имя персонажа, действие).
📌 Правила:
1. Только тот, кто сначала "picked", может "ate".
2. Если кто-то "dropped", он больше не владеет объектом.
3. Нужно выяснить, кто съел яблоко, и проверить: мог ли он это сделать по правилам?
🧠 Задача:
Напиши функцию who_ate(actions: list[tuple[str, str]]) -> str, которая возвращает:
- "OK" — если всё законно
- "CHEATER" — если съевший не имел права
---
✅ Решение с разбором:
```python
def who_ate(actions):
holding = set()
eater = None
for name, action in actions:
if action == "picked":
holding.add(name)
elif action == "dropped":
holding.discard(name)
elif action == "ate":
eater = name
if name in holding:
return "OK"
else:
return "CHEATER"
return "NO ONE ATE"
```
📌 **Как это работает:**
- `holding` — это множество тех, кто в данный момент "держит" объект.
- Как только кто-то `"ate"`, мы сразу проверяем: находится ли он в `holding`?
- Если нет — значит, он **съел чужое яблоко**. Подмена! 🤯
---
🔍 **Разбор на примере:**
```python
# Charlie picked → OK
# Charlie ate → всё ещё держит → OK
print(who_ate([
("Charlie", "picked"),
("Charlie", "ate")
])) # OK
# Alice picked, потом dropped, потом ate → нарушила правила
print(who_ate([
("Alice", "picked"),
("Alice", "dropped"),
("Alice", "ate")
])) # CHEATER
```
---
💡 Подвох в том, что многие решают задачу, просто считая количество действий, **не отслеживая актуальное владение** объектом.
📦 Задача хороша для собесов — проверяет внимание к деталям и мышление в терминах состояний. ge: 18 для чисел или вложенных структур. Сборка требует Rust toolchain, но результат стоит того: например, валидация списка из 10к элементов занимает миллисекунды.
🤖 GitHub
@python_interviewlambda, отложенное выполнение
📌 Условие
Что выведет следующий код?
funcs = []
for i in range(5):
funcs.append(lambda: i)
results = [f() for f in funcs]
print(results)
❓ Вопросы
1. Почему вывод может не соответствовать ожиданиям [0, 1, 2, 3, 4]?
2. Что именно "запоминает" lambda внутри цикла?
3. Как переписать код, чтобы результат был [0, 1, 2, 3, 4]?
🔍 Разбор
✅ Ожидаемый (неправильный) вывод:
[4, 4, 4, 4, 4]🔧 Почему так происходит - Все
lambda внутри funcs замыкают одну и ту же переменную `i`.
- К моменту выполнения f() переменная i уже равна 4 — и так для всех функций.
⚠️ Подвох
lambda: i не захватывает значение, а ссылается на переменную, которая будет изменяться при каждой итерации цикла.
В итоге — все lambda ссылаются на одно и то же `i`, которое стало равно 4 к концу цикла.
🧠 Решение
Нужно "зафиксировать" значение i, передав его как аргумент по умолчанию в lambda:
for i in range(5):
funcs.append(lambda i=i: i)
Теперь результат будет:
[0, 1, 2, 3, 4]📌 Это один из самых частых подвохов в Python, особенно при использовании лямбда-функций в генераторах и UI-коллбеках.
list и dict
📌 Условие
Что выведет следующий код?
def append_to_list(value, my_list=[]):
my_list.append(value)
return my_list
print(append_to_list(1))
print(append_to_list(2))
print(append_to_list(3))
❓ Вопросы
1. Почему результат выглядит неожиданно?
2. Как исправить это поведение?
3. Когда стоит использовать изменяемые аргументы по умолчанию — если вообще стоит?
🔍 Разбор
✅ Ожидаемый вывод:
[1] [1, 2] [1, 2, 3]🔧 Почему так происходит - Аргументы по умолчанию вычисляются один раз — во время определения функции, а не при каждом вызове. - Значение
my_list=[] создаётся один раз и затем используется повторно при всех вызовах.
- Все вызовы append_to_list изменяют один и тот же список.
⚠️ Подвох
Это один из самых коварных багов в Python, особенно среди начинающих — кажется, что my_list должен быть новым на каждый вызов, но это не так.
🧠 Вывод
- Никогда не используй изменяемые типы (list, dict, set) как значения по умолчанию.
- Вместо этого используй None и создавай новый объект вручную:
def append_to_list(value, my_list=None):
if my_list is None:
my_list = []
my_list.append(value)
return my_list
✅ Тогда вывод будет:
[1] [2] [3]📌 Это правило относится ко всем изменяемым типам:
[], {}, set() и кастомные классы.
@python_job_interview Depends(RateLimiter(times=2, seconds=5)) к эндпоинту и он начнет отклонять запросы после двух обращений в пятисекундном окне. Под капотом работает Lua-скрипт, который эффективно считает запросы без лагов.
Интересные фишки:
— Поддержка вебсокетов через WebSocketRateLimiter
— Кастомизация идентификаторов
— Множественные лимиты на один роут
🤖 GitHub
@python_job_interviewcounter(start), которая возвращает функцию-счётчик. Каждый вызов этой функции увеличивает значение на 1.
Пример:
c = counter(10)
print(c()) # 11
print(c()) # 12
print(c()) # 13
d = counter(100)
print(d()) # 101
print(c()) # 14 ← работает независимо
🎯 Подвох:
- Нельзя использовать глобальные переменные
- Нужно использовать замыкание
- Без nonlocal — не заработает
✅ Решение:
def counter(start):
count = start
def inner():
nonlocal count
count += 1
return count
return inner
# Проверка
a = counter(5)
print(a()) # 6
print(a()) # 7
b = counter(100)
print(b()) # 101
print(a()) # 8
🧠 Объяснение подвоха:
- counter возвращает функцию, внутри которой count сохраняется в замыкании
- nonlocal нужен, чтобы изменить внешнюю переменную, а не просто читать её
- Каждое замыкание имеет своё независимое состояние
⚠️ Без nonlocal count, Python создаст локальную count внутри inner(), и UnboundLocalError — гарантирован
🛠️ Применяется в:
• Реализации генераторов состояния
• Мини-хранилищах внутри функций
• Кеширующих функциях и декораторах
@python_job_interviewcollections.defaultdict(list) для удобства, и пишете такой код:
from collections import defaultdict
actions = defaultdict(list)
def track(user_id, action):
actions[user_id].append(action)
track('alice', 'login')
track('bob', 'view')
track('alice', 'logout')
# Теперь вы хотите скопировать этот словарь
copy_actions = actions.copy()
# Допишем в оригинал
track('bob', 'logout')
# Посмотрим, как выглядит копия
print(copy_actions['bob']) # Что будет напечатано?
🧠 Вопрос:
Что будет напечатано? Почему?
Как сделать так, чтобы copy_actions не изменился при добавлении новых действий в actions?
💥 Подвох
Метод copy() копирует только верхний уровень словаря. То есть, списки значений не копируются — это всё те же самые объекты в памяти. Поэтому при track('bob', 'logout') список actions['bob'] изменяется, и это тот же самый список, что лежит в copy_actions['bob'].
➡️ Ответ: print(copy_actions['bob']) напечатает ['view', 'logout'].
✅ Как правильно?
Чтобы избежать такой проблемы, используйте глубокое копирование:
import copy
copy_actions = copy.deepcopy(actions)
Теперь copy_actions не изменится при дальнейшем редактировании actions.
📌 Вывод
Даже опытные разработчики иногда забывают: copy() не копирует вложенные структуры данных!
Если в значениях словаря лежат мутабельные объекты, обязательно подумайте — а не нужен ли вам deepcopy()?
🧪 Попробуйте изменить defaultdict(list) на обычный dict — и посмотрите, что изменится.def update_dict(key, value, d={}):
d[key] = value
return d
dict1 = update_dict('a', 1)
dict2 = update_dict('b', 2, {})
dict3 = update_dict('c', 3)
print("dict1 =", dict1)
print("dict2 =", dict2)
print("dict3 =", dict3)
— Варианты ответа:
A.
dict1 = {'a': 1}
dict2 = {'b': 2}
dict3 = {'c': 3}
B.
dict1 = {'a': 1, 'c': 3}
dict2 = {'b': 2}
dict3 = {'a': 1, 'c': 3}
C.
dict1 = {'a': 1}
dict2 = {'b': 2}
dict3 = {'a': 1, 'c': 3}
Какой из этих ответов правильный и почему?🧐
— Подсказка: аргументы по умолчанию в Python вычисляются только один раз - при определении функции. Словарь, как и список, является изменяемым объектом.
В функции update_dict параметр d={} создается один раз и используется для всех вызовов, где не передается явно другой словарь.
— Правильный ответ: B
Объяснение:
1️⃣ dict1 = update_dict('a', 1) → используется словарь по умолчанию → {'a': 1}
2️⃣ dict2 = update_dict('b', 2, {}) → создан новый словарь → {'b': 2}
2️⃣ dict3 = update_dict('c', 3) → снова используется исходный словарь → {'a': 1, 'c': 3}
4️⃣ dict1 тоже изменится, так как это ссылка на тот же объект → {'a': 1, 'c': 3}
Итоговый вывод:
dict1 = {'a': 1, 'c': 3}
dict2 = {'b': 2}
dict3 = {'a': 1, 'c': 3}
@python_job_interview
Уже доступно! Исследование Telegram 2025 — ключевые инсайты года 
