Python вопросы с собеседований
Вопросы с собеседований по Python @workakkk - админ @machinelearning_interview - вопросы с собесдований по Ml @pro_python_code - Python @data_analysis_ml - анализ данных на Python @itchannels_telegram - 🔥 главное в ит РКН: clck.ru/3FmrFd
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Python вопросы с собеседований
تُعد قناة Python вопросы с собеседований (@python_job_interview) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 24 967 مشتركاً، محتلاً المرتبة 5 488 في فئة التكنولوجيات والتطبيقات والمرتبة 26 804 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 24 967 مشتركاً.
بحسب آخر البيانات بتاريخ 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
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
