Python вопросы с собеседований
Вопросы с собеседований по Python @workakkk - админ @machinelearning_interview - вопросы с собесдований по Ml @pro_python_code - Python @data_analysis_ml - анализ данных на Python @itchannels_telegram - 🔥 главное в ит РКН: clck.ru/3FmrFd
Ko'proq ko'rsatish📈 Telegram kanali Python вопросы с собеседований analitikasi
Python вопросы с собеседований (@python_job_interview) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 24 822 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 5 258-o'rinni va Rossiya mintaqasida 26 472-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 24 822 obunachiga ega bo‘ldi.
25 Avgust, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni -44 ga, so‘nggi 24 soatda esa 0 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 6.01% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 2.76% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 1 492 marta ko‘riladi; birinchi sutkada odatda 684 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 6 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent github, api, собеседование, git, docker kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“Вопросы с собеседований по Python
@workakkk - админ
@machinelearning_interview - вопросы с собесдований по Ml
@pro_python_code - Python
@data_analysis_ml - анализ данных на Python
@itchannels_telegram - 🔥 главное в ит
РКН: clck.ru/3FmrFd”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 28 Avgust, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
{user_input}
\"\n\n# Предположим, функция html() экранирует опасные символы\nsafe_output = html(template)\n\n\nЗачем это нужно?\n\nИдея проста: обеспечить безопасность по умолчанию при работе с внешними данными. Сегодня f-строки невероятно удобны, но могут стать причиной уязвимостей, если не учитывать контекст.\n\nПример:\n\n\n# Опасный подход с f-строкой\nquery = f\"SELECT * FROM users WHERE name = '{user_input}'\"\n\n\nС t-строками можно заранее создать шаблон и безопасно вставить данные позже, минимизируя риски.\n\nПочему мнения разделились?\n\nМногие разработчики задаются вопросом: зачем ещё один способ форматирования строк, если уже есть:\n\n- старые добрые `%`-форматирование,\n- метод .format(),\n- f-строки,\n- и сторонние шаблонизаторы вроде Jinja2.\n\nНекоторые опасаются, что добавление нового синтаксиса лишь усложнит язык без серьёзной необходимости.\n\nСторонники t-строк, однако, видят их потенциал в упрощении безопасной работы с текстом прямо в стандартной библиотеке Python.\n\nЗаключение\n\nT-строки — это попытка добавить в Python инструмент, который обеспечит безопасность шаблонов без привлечения сторонних библиотек. Будет ли это востребовано или останется малоиспользуемой функцией? Время покажет.\n\n🔗 Полное описание: [PEP 750](https://peps.python.org/pep-0750/)\n\nА как ты относишься к новым t-строкам? 💬","datePublished":"2025-05-07T16:53:03Z","dateModified":"2025-05-07T16:53:03Z","author":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"publisher":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"commentCount":2,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":3334},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":28},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":22},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2}]}},{"@type":"ListItem","position":16,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1101","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1101","mainEntityOfPage":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1101","headline":"📝 Как составить резюме, чтобы попасть в Magnificent 7: анализ кейса Недавно инженер поделился своим резюме, к…","articleBody":"📝 Как составить резюме, чтобы попасть в Magnificent 7: анализ кейса\n\nНедавно инженер поделился своим резюме, которое помогло ему получить предложение работы от одной из rjvgfybb Magnificent 7 (Apple, Microsoft, Google, Amazon, Meta, Nvidia, Tesla).\n\nMagnificent 7 (в переводе — «Великолепная семёрка») — это современное неофициальное название семи крупнейших и самых влиятельных технологических компаний США, которые лидируют на фондовом рынке, в инновациях и в масштабе бизнеса.\n\nРазберём, что сделало его резюме успешным и чему можно научиться.\n\n📌 Главные выводы из резюме:\n\n1. Фокус на достижениях, а не обязанностях.\n\nМногие кандидаты в резюме просто перечисляют, *что они делали*, например:\n\n- “Разрабатывал API”\n- “Поддерживал базу данных”\n- “Писал скрипты для автоматизации”\n\n⚠️ Это описывает обязанности, но не показывает ценность или результат работы.\n\nВ успешном резюме инженер вместо этого написал, чего он достиг благодаря своей работе:\n\n✅ “Разработал API, который сократил время обработки данных на 30%” \n✅ “Оптимизировал запросы к базе данных, уменьшив среднее время ответа с 2 секунд до 0.5 секунд” \n✅ “Автоматизировал процесс деплоя, снизив количество ошибок на 15%”\n\nТакой подход показывает, как конкретно ваша работа помогла команде или бизнесу. \nРаботодатель видит результаты, которые вы приносите, а не просто описание того, что вы делали.\n\n💡 Почему это важно?\n\nBig Tech-компании ищут инженеров, которые:\n\n- Умеют оценивать влияние своей работы\n- Думают о метриках успеха\n- Приносят измеримый результат\n\nЕсли в резюме нет цифр, улучшений или влияния на процесс — работодатель сам должен это додумывать. \nА успешное резюме снимает вопросы и сразу показывает: “Вот что я сделал, вот как я улучшил продукт/процесс/результат.”\n\n\n2. Лаконичность и компактность.\n\n✅ 1 страница \n✅ Чёткая структура: “Опыт”, “Навыки”, “Образование” \n✅ Без фото, графиков, цветных рамок — чистый текст\n\n3. Цифры везде, где это возможно.\n\nЛюбое достижение сопровождается конкретной метрикой: улучшение производительности, сокращение времени, рост количества пользователей. \nДаже небольшие улучшения указаны численно.\n\n4. Поддержка через проекты с открытым кодом.\n\nИнженер приложил ссылку на GitHub с реальными проектами — это усилило доверие к нему Как с специалисту.\n\n5. Навыки — только релевантные вакансии.\n\nВ разделе Skills нет «MS Word» или «PowerPoint». \nТолько языки, технологии, инструменты, которые нужны для позиции (Python, Kubernetes, CI/CD, etc.).\n\n6. Интерншипы и стажировки — это опыт.\n\nКаждый опыт, даже в рамках стажировки, описан с результатами. \nВакансии в топ-компаниях ценят любую практику в реальной команде.\n\n---\n\n🎯 Что важно для Big Tech:\n\n✅ Результаты > Задачи. \n✅ Цифры. \n✅ 1 страница. \n✅ GitHub/портфолио. \n✅ Релевантные навыки.\n\n---\n\n🔥 Совет:\n\nВаше резюме — это реклама вас как продукта. \nПокажите пользу, которую вы можете принести, а не просто список обязанностей.\n\n➡️ Статья","datePublished":"2025-05-06T10:00:15Z","dateModified":"2025-05-06T10:00:15Z","author":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"publisher":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"commentCount":3,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2674},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":15},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":42},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3}]}},{"@type":"ListItem","position":17,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1100","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1100","mainEntityOfPage":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1100","headline":"🌟 Dynaconf — управление конфигурациями в Python без головной боли. Этот проект предлагает унифицированный спо…","articleBody":"🌟 Dynaconf — управление конфигурациями в Python без головной боли. Этот проект предлагает унифицированный способ работы с конфигурациями: от простых .toml-файлов до интеграции с Hashicorp Vault для хранения секретов. \n\nПроект выделяет из общей массы поддержка 5+ форматов с автоматическим парсинго, разделение настроек по средам, защита секретов через .gitignore и возможность использовать Redis/Vault. Для старта достаточно pip install dynaconf и одной команды dynaconf init, которая сгенерирует все необходимые файлы. \n\n🤖 GitHub\n\n@python_job_interview","datePublished":"2025-05-05T14:41:01Z","dateModified":"2025-05-05T14:41:01Z","author":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"publisher":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2284},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":8},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":19}]}},{"@type":"ListItem","position":18,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1099","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1099","mainEntityOfPage":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1099","headline":"Порекомендуйте друга в Ozon Tech и получите 150 000 ₽. Важно: IT-команда ведущего e-com ищет специалистов уро…","articleBody":"Порекомендуйте друга в Ozon Tech и получите 150 000 ₽. \n\nВажно: IT-команда ведущего e-com ищет специалистов уровня senior+ в Data Science. Программа работает для тех, кто не работает в Ozon. \n\nПодробнее о том, за какие вакансии можно получить вознаграждение, здесь ⬅️","datePublished":"2025-05-05T12:41:43Z","dateModified":"2025-05-26T14:08:46Z","author":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"publisher":{"@type":"Organization","name":"Python вопросы с собеседований","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview","image":"https://img.tlmtr.io/c/1MHiSS/5474186619528527464?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2482},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":2},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":7}]}},{"@type":"ListItem","position":19,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1098","url":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1098","mainEntityOfPage":"https://telemetr.io/uz/channels/1635717658-python_job_interview/posts/1098","headline":"🧩 Python‑задача: построить резолвер зависимостей для «мини‑PyPI» Нужно написать ядро пакетного менеджера — ал…","articleBody":"🧩 Python‑задача: построить резолвер зависимостей для «мини‑PyPI»\n\nНужно написать ядро пакетного менеджера — алгоритм, выбирающий набор совместимых версий библиотек под заданные ограничения. \nЗадача напоминает работу pip, npm или cargo, но в упрощённом формате, достаточном для тренировки графовых алгоритмов, backtracking и оптимизаций.\n\n## 📜 Входные данные\n\n1. catalog.json — «репозиторий» пакетов. \n \n {\n \"pandas\": {\n \"1.1.0\": { \"depends\": { \"numpy\": \">=1.17,<1.20\" } },\n \"1.3.5\": { \"depends\": { \"numpy\": \">=1.19,<1.22\", \"python-dateutil\": \">=2.7\" } }\n },\n \"numpy\": {\n \"1.18.5\": { \"depends\": {} },\n \"1.19.2\": { \"depends\": {} },\n \"1.21.0\": { \"depends\": {} }\n },\n \"python-dateutil\": {\n \"2.8.0\": { \"depends\": { \"six\": \">=1.5\" } },\n \"2.8.2\": { \"depends\": { \"six\": \">=1.5\" } }\n },\n \"six\": {\n \"1.14.0\": { \"depends\": {} },\n \"1.16.0\": { \"depends\": {} }\n }\n }\n \n *Ключ* — имя пакета; *значения* — версии → словарь зависимостей (`depends`). \n У каждой зависимости указан диапазон версий по SemVer‑синтаксису >=a, 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_interviewt перед строкой, например:
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_interview