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 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), канал підтримує актуальність та високий рівень охоплення публікацій. Аналітика показує, що аудиторія активно взаємодіє з контентом, що робить його важливою точкою впливу в категорії Технології та додатки.
t перед строкой, например:
t"Привет, {name}!"
Но ключевое отличие: вместо немедленного преобразования переменных в строку, как это делает f-строка, t-строка создаёт объект Template, который можно обработать позже. Это позволяет, например, безопасно подставлять пользовательские данные, снижая риск атак (XSS, SQL-инъекции и др.).
Пример использования:
from string.templatelib import Template
user_input = "<script>alert('XSS')</script>"
template = t"<p>{user_input}</p>"
# Предположим, функция html() экранирует опасные символы
safe_output = html(template)
Зачем это нужно?
Идея проста: обеспечить безопасность по умолчанию при работе с внешними данными. Сегодня f-строки невероятно удобны, но могут стать причиной уязвимостей, если не учитывать контекст.
Пример:
# Опасный подход с f-строкой
query = f"SELECT * FROM users WHERE name = '{user_input}'"
С t-строками можно заранее создать шаблон и безопасно вставить данные позже, минимизируя риски.
Почему мнения разделились?
Многие разработчики задаются вопросом: зачем ещё один способ форматирования строк, если уже есть:
- старые добрые `%`-форматирование,
- метод .format(),
- f-строки,
- и сторонние шаблонизаторы вроде Jinja2.
Некоторые опасаются, что добавление нового синтаксиса лишь усложнит язык без серьёзной необходимости.
Сторонники t-строк, однако, видят их потенциал в упрощении безопасной работы с текстом прямо в стандартной библиотеке Python.
Заключение
T-строки — это попытка добавить в Python инструмент, который обеспечит безопасность шаблонов без привлечения сторонних библиотек. Будет ли это востребовано или останется малоиспользуемой функцией? Время покажет.
🔗 Полное описание: [PEP 750](https://peps.python.org/pep-0750/)
А как ты относишься к новым t-строкам? 💬 pip install dynaconf и одной команды dynaconf init, которая сгенерирует все необходимые файлы.
🤖 GitHub
@python_job_interviewpip, npm или cargo, но в упрощённом формате, достаточном для тренировки графовых алгоритмов, backtracking и оптимизаций.
## 📜 Входные данные
1. catalog.json — «репозиторий» пакетов.
{
"pandas": {
"1.1.0": { "depends": { "numpy": ">=1.17,<1.20" } },
"1.3.5": { "depends": { "numpy": ">=1.19,<1.22", "python-dateutil": ">=2.7" } }
},
"numpy": {
"1.18.5": { "depends": {} },
"1.19.2": { "depends": {} },
"1.21.0": { "depends": {} }
},
"python-dateutil": {
"2.8.0": { "depends": { "six": ">=1.5" } },
"2.8.2": { "depends": { "six": ">=1.5" } }
},
"six": {
"1.14.0": { "depends": {} },
"1.16.0": { "depends": {} }
}
}
*Ключ* — имя пакета; *значения* — версии → словарь зависимостей (`depends`).
У каждой зависимости указан диапазон версий по SemVer‑синтаксису >=a,<b.
2. requirements.txt — то, что хочет пользователь:
pandas>=1.1,<1.4 python-dateutil==2.8.2## 🔧 Задача Написать функцию
resolve(catalog: dict[str, dict[str, dict]],
requirements: list[str]) -> dict[str, str]
которая возвращает словарь
{package: chosen_version} — единственную консистентную конфигурацию, удовлетворяющую всем ограничениям, *либо* возбуждает UnresolvableError.
### Правила
1. Версия должна лежать в пересечении *всех* диапазонов, навешанных на пакет.
2. Если диапазон пуст — конфликты нельзя игнорировать.
3. Разрешение идёт по принципу «самая новая подходящая версия» (Greedy‑latest), но если она приводит к заведомому конфликту, надо откатиться («backtrack») и попробовать более старую.
4. Каталог может быть большим (≥ 10 000 пакетов), алгоритм должен укладываться в секунды.
5. Допустимо использовать только стандартную библиотеку + packaging.version/packaging.specifiers (pip‑compatible сравнение версий).
## 🏁 Дополнительные челленджи
* Кэшировать результаты проверки диапазонов, чтобы не пересчитывать одно и то же.
* Оптимизировать порядок обхода графа (например, сначала пакеты с меньшим числом разрешимых версий).
* Добавить «экзотики»: опциональные зависимости, extras (`pandas[perf]`) или marker‑выражения (`sys_platform == "linux"`).
---
# ✅ Референс‑решение (однофайловое, python 3.11)
> *Не читайте решение в комментариях, пока не попробуете решить сами!*
@python_job_interviewSmartCache, который работает следующим образом:
- Метод put(key: str, value: Any):
- Сохраняет значение по ключу.
- Если суммарный объем памяти, занимаемый всеми элементами, превышает лимит (например, 10 MB), автоматически удаляются наименее "ценные" элементы.
- Метод get(key: str) -> Any:
- Возвращает значение по ключу.
- Увеличивает счётчик использования элемента.
- Если элемент отсутствует — возвращает None.
Что значит "ценность" элемента:
- Ценность = количество обращений (`hit count`) к элементу.
- При очистке кэша сначала удаляются элементы с наименьшим количеством обращений.
Ограничения:
- Класс должен корректно считать объём памяти, занимаемый элементами.
- Нужно учитывать, что элементы могут быть сложными структурами (`dict`, list, вложенные объекты).
- Решение должно быть эффективным: операции должны быть быстрыми даже при большом количестве элементов.
---
▪️ Подсказки:
- Для оценки размера объектов можно использовать модуль sys.getsizeof, но для сложных вложенных структур нужен рекурсивный подсчет.
- Для хранения частоты обращений стоит использовать дополнительную структуру данных (`collections.Counter` или `dict`).
- При очистке лучше сначала группировать элементы по "ценности", а затем удалять самые "дешевые".
---
▪️ Что оценивается:
- Умение работать с ограничениями по памяти.
- Аккуратная обработка ссылок и размеров объектов.
- Эффективность очистки кэша.
- Чистота и читаемость кода.
---
▪️ Разбор возможного решения:
Идея архитектуры:
- Храним:
- storage: словарь {key: value}.
- hits: счётчик {key: hit_count}.
- size: общий размер всех объектов.
- При put():
- Добавляем элемент.
- Пересчитываем суммарный размер.
- Если размер превышает лимит:
- Удаляем наименее популярные элементы до тех пор, пока не уложимся в лимит.
- При get():
- Увеличиваем hit_count элемента.
- Возвращаем значение или None.
Оценка размера объектов:
- Простого sys.getsizeof недостаточно для коллекций.
- Нужна функция, рекурсивно подсчитывающая размер всех вложенных объектов.
Мини-пример функции подсчета размера:
import sys
def deep_getsizeof(obj, seen=None):
"""Рекурсивно считает память объекта и его вложенных объектов"""
size = sys.getsizeof(obj)
if seen is None:
seen = set()
obj_id = id(obj)
if obj_id in seen:
return 0
seen.add(obj_id)
if isinstance(obj, dict):
size += sum([deep_getsizeof(v, seen) + deep_getsizeof(k, seen) for k, v in obj.items()])
elif isinstance(obj, (list, tuple, set, frozenset)):
size += sum(deep_getsizeof(i, seen) for i in obj)
return size
Мини-пример интерфейса `SmartCache`:
class SmartCache:
def __init__(self, max_size_bytes):
self.max_size = max_size_bytes
self.storage = {}
self.hits = {}
self.total_size = 0
def put(self, key, value):
# добавить логику добавления и очистки при переполнении
pass
def get(self, key):
# увеличить hit_count и вернуть значение
pass
🔖 Дополнительные вопросы:
- Как ускорить очистку кэша без полного перебора всех элементов?
- Как сделать потокобезопасную версию кэша?
- Как адаптировать SmartCache для распределённой архитектуры (кэш между несколькими машинами)?
@python_job_interviewВ первой строке заданы два натуральных числа N и M (0 < N, M ≤ 100 000). Во второй строке перечислены N элементов первого множества (целые числа через пробел). В третьей строке — M элементов второго множества (целые числа через пробел). Все числа по модулю не превышают 10<sup>9</sup>.— Выходные данные
Для каждого из M чисел выведите в отдельной строке: - "IN", если число присутствует в обоих множествах - "OUT", если число есть только в одном из множеств - "MISS", если числа нет ни в одном множестве— Примеры: Входные данные:
5 4 10 20 30 40 50 20 25 40 60Выходные данные:
IN OUT IN MISSЖду ваших вариантов решений 📝 @python_job_interview
name = "Alice"
greeting = t"Hello, {name}!" # t-строка
Вместо немедленной подстановки, как в f"...", t"..." создает шаблон с выражениями как параметрами.
🔐 Зачем это нужно?
✅ Безопасность при генерации SQL, HTML, JSON
✅ Улучшение инструментов и проверки типов (через static analysis)
✅ Контроль над контекстом исполнения (больше нельзя просто вставить переменную как есть — нужно передать её явно)
📦 Использование:
t-строки — это первый шаг к "template string literals" как в TypeScript.
Можно использовать с функциями:
def html(template: T[str]) -> SafeHTML:
...
html(t"<div>{user_input}</div>")
💡 Почему это важно?
Старый код:
f"SELECT * FROM users WHERE name = '{user_name}'"
может привести к SQL-инъекциям и XSS.
t-строки — безопасная альтернатива с встроенной защитой.
🛡 Пример: безопасный HTML
template = t"<p>{user_input}</p>"
html_output = html(template)
# <p><script>alert('bad')</script></p>
Функция html() может вернуть не просто строку, а полноценный HTMLElement.
Больше никакой "грязи" — всё чисто и типобезопасно.
🔍 Работа с шаблоном
t-строки позволяют получить доступ к содержимому:
template = t"Hello {name}!"
template.strings # ("Hello ", "!")
template.values # (name,)
template.interpolations[0].format_spec # ">8"
Можно и вручную собрать шаблон:
Template("Hello ", Interpolation(value="World", expression="name"), "!")
🚀 Вывод:
t"..." — шаг к безопасным шаблонам и типизации строк в Python.
Готовься к будущему Python — безопасному по умолчанию.
📌 Подробнее здесь
@pythonlВ первой строке входных данных содержатся натуральные числа N и К ( 0 < N, K ≤ 100 000). Во второй строке задаются N элементов первого массива, отсортированного по возрастанию, а в третьей строке - К элементов второго массива. Элементы обоих массивов - целые числа, каждое из которых по модулю не превосходит 109— Выходные данные
Требуется для каждого из К чисел вывести в отдельную строку "YES", если это число встречается в первом массиве, и "NO" в противном случае.— Примеры: входные данные
10 5 123 4 5 6 7 8 9 10 -2 0 4 9 12выходные данные
NO NO YES YES NOСкидывайте свои решения в комментарии🧐 @python_job_interview
mydaemon), который запускается через systemd unit и, согласно логам, должен работать постоянно.
❓ Но вот странность:
systemctl status mydaemon показывает, что сервис активен.
Однако при выполнении ps aux | grep mydaemon — процесса в списке нет.
top, htop, pgrep, pidof — тоже ничего не показывают.
Но при перезапуске systemd-сервиса (systemctl restart mydaemon) — в логах появляется запись о запуске, ошибок нет, а поведение не меняется.
Вопрос:
что происходит и как найти реальный процесс?Подсказки: Попробуйте посмотреть, какой тип сервиса указан в systemd unit-файле. Изучите, куда уходит stdout/stderr
.
Подумайте, может ли ExecStart запускать shell-обёртку, а не сам процесс.
Что покажет systemctl show -p MainPID mydaemon?
Подвох и решение:
Часто в unit-файле могут писать:
```ini
Type=simple
ExecStart=/bin/bash -c 'sleep 9999'```
Systemd считает, что bash — это основной процесс (MainPID), но он сразу завершается, передав выполнение sleep. Однако поскольку Type=simple, systemd не отслеживает дочерние процессы, и MainPID исчезает — ps и pgrep по имени mydaemon ничего не покажут, а дочерний процесс (sleep 9999) работает, но под другим именем.
Решение:
Либо указать Type=forking и использовать PIDFile.
Либо не использовать bash -c, а запускать нужный бинарь напрямую.
Либо использовать Type=exec (в systemd >240) или Type=notify с proper daemon tools.user, login/logout).
Найди тех, кто зашел, но не вышел.
📜 Пример:
logs = [
("alice", "login"),
("bob", "login"),
("alice", "logout"),
("dave", "login"),
("bob", "logout"),
("carol", "login"),
("dave", "logout")
]
________
💻 Решение:
from collections import defaultdict
def find_stuck_users(logs):
counter = defaultdict(int)
for user, action in logs:
if action == "login":
counter[user] += 1
elif action == "logout":
counter[user] -= 1
return sorted([user for user, count in counter.items() if count > 0])
🛠Ответ: "carol"
#Python #Challenge #DevPuzzle
@python_job_interview
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123, [])
list3 = extendList('a')
print("list1 =", list1)
print("list2 =", list2)
print("list3 =", list3)
Варианты ответа:
A.
list2 = [123]
list3 = ['a']
B.
list2 = [123]
list3 = [10, 'a']
C.
list2 = [123]
list3 = [10, 'a']
D.
list2 = [123]
list3 = ['a']
❓ Как думаешь, какой ответ правильный и почему?
Подвох: аргументы по умолчанию в Python вычисляются один раз — при определении функции.
🔸 В extendList(val, list=[]) — этот list=[] сохраняется один и тот же объект списка для всех вызовов функции, где не передаётся list.
Что происходит:
list1 = extendList(10)
→ list=[] по умолчанию
→ list = [10]
→ list1 → [10]
list2 = extendList(123, [])
→ передали новый список
→ list = [123]
→ list2 → [123]
list3 = extendList('a')
→ снова использован тот же список, что и в list1
→ list = [10, 'a']
→ list3 → [10, 'a']
→ и list1 тоже теперь [10, 'a'], потому что это один и тот же объект
Вывод будет:
list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']
Вже доступно! Дослідження Telegram за 2025 — головні інсайти року 
