Python: задачки и вопросы
6.97K subscribers
1.35K photos
1 video
1 file
135 links
Вопросы и задачки для подготовки к собеседованиям и прокачки навыков

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Другие наши проекты: https://tprg.ru/media
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Python: задачки и вопросы
Развёрнутое пояснение:

1. Цикл for event_type in ('click', 'scroll') начинает первую итерацию: event_type = 'click'.

2. На этой итерации определяется функция handler(e=event_type). Значение по умолчанию для e вычисляется сейчас и сохраняется как 'click' внутри объекта функции.

3. Переменная event_type в теле handler не является локальной: она свободная и будет искаться в объемлющей области видимости во время вызова.

4. Вторая итерация: event_type = 'scroll'. Определяется новая функция handler, её значение по умолчанию для e — 'scroll'.

5. После цикла event_type остаётся равной 'scroll', так как это последнее значение итерируемого.

6. Вызов handlers[0]() использует значение по умолчанию e='click' и берёт event_type='scroll' из замыкания, возвращая ('click', 'scroll').

7. Вызов handlers[1]() использует e='scroll' и event_type='scroll', возвращая ('scroll', 'scroll').

Почему это важно: разница между ранним и поздним связыванием встречается при создании колбэков, обработчиков событий и фабрик функций в цикле. Ошибка приводит к тому, что все созданные обработчики ссылаются на последнее значение переменной цикла, а использование параметра по умолчанию — распространённый способ зафиксировать нужное значение для каждой функции.
1
Плохо помните математику и боитесь её, но она нужна для работы? Присмотритесь к курсу «Математика для анализа данных» от Практикума PRO.

В рамках курса вы решите 100+ практических задач и подготовитесь к математической части собеседований аналитиков и специалистов по data science. А для этого погрузитесь в четыре раздела математики:

1. Линейная алгебра: векторы, матрицы, скалярное произведение, нормы, определители, смена базиса.

Зачем. Работа с данными держится на линейной алгебре. Вектор — это просто строка с характеристиками объекта (например, клиент с параметрами: возраст, доход, количество покупок). Матрица — это вся таблица с данными. Линейная алгебра учит превращать текст или картинки в наборы чисел и вычислять, насколько объекты похожи друг на друга (например, для рекомендательных систем или поисковиков).


2. Функции: линейные и полиномиальные, логарифмы, модули, композиции функций, графики.

Зачем. Показывает, как описывать реальные процессы формулами. Например, как цена квартиры зависит от её площади или как меняется спрос на товар. Логарифмы позволяют работать с огромными разбросами значений (когда у одного пользователя 2 подписчика, а у другого — 10 миллионов), приводя их к удобному масштабу.


3. Матанализ: пределы, производные, интегралы, функции нескольких переменных и градиентный спуск.

Зачем. Помогает находить наилучшие (оптимальные) решения и обучать алгоритмы. Производная показывает скорость и направление изменений. Алгоритм градиентного спуска использует производные, чтобы заставлять нейросети и модели машинного обучения совершать всё меньше ошибок. Это главный механизм «обучения» ИИ.


4. Теорвер и матстат: дискретные и непрерывные случайные величины, распределения, теорема Байеса, корреляция, центральная предельная теорему, А/B-тестирование, гипотезы, p-value.

Зачем. Учит принимать обоснованные решения в условиях неопределенности. Статистика нужна, чтобы измерять взаимосвязи через A/B-тесты (например, действительно ли новая кнопка на сайте увеличила продажи или это просто случайность) и оценить надежность выводов.


Можно прийти даже с забытыми школьными знаниями. Формулы разбирают на понятных жизненных задачах с кодом на Python и визуализациями. Есть преподаватель математики, который отвечает на вопросы по сложным задачам, а встроенный ИИ-помощник объяснит одну и ту же формулу разными словами.

💻 Протестировать платформу и формат обучения, а также пройти первый урок бесплатно: https://tprg.ru/WcrJ
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Python: задачки и вопросы
Развёрнутое пояснение:

1. Вызов await t(1) запускает первую корутину: на печать идёт 1, затем await sleep(0) приостанавливает выполнение main и отдаёт управление event loop.

2. create_task(t(3)) только планирует фоновую задачу в очередь event loop, но не запускает её немедленно.

3. await t(2) печатает 2 и тоже приостанавливается на sleep(0).

4. Event loop видит три готовых продолжения: t(1), запланированная t(3) и main после t(2). Порядок FIFO, поэтому сначала возобновляется t(1), которая печатает 2 и завершается.

5. Следующей запускается t(3): печатается 3, затем await sleep(0) приостанавливает её.

6. Затем event loop возвращает управление в main после await t(2), где сразу выполняется await x и main ждёт завершения t(3).

7. Event loop возобновляет t(3), печатается 4, задача завершается.

8. В результате на печать идёт последовательность 122334.

Почему это важно: в асинхронном коде побочные эффекты и порядок записи строк не всегда совпадают с порядком выполнения. sleep(0) — не пустая операция, а точка уступки управления, после которой event loop выбирает следующую задачу из очереди. Это влияет на порядок логов, обновление кэша, коммитов состояния и других операций с побочными эффектами, поэтому важно понимать, что create_task планирует задачу, а await передаёт управление.
2
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Python: задачки и вопросы
Развёрнутое пояснение:

1. В строке from decimal import Decimal импортируется тип Decimal.

2. Выражение Decimal('0.1') + Decimal('0.2') выполняет точное десятичное сложение и даёт Decimal('0.3').

3. Сравнение a == 0.3 сравнивает Decimal с float. Python преобразует float 0.3 в Decimal через его двоичное приближение, которое не равно Decimal('0.3'), поэтому результат False.

4. Сравнение a == Decimal('0.3') сравнивает два одинаковых Decimal, поэтому True.

5. float(a) превращает Decimal('0.3') в float 0.3, и сравнение с литералом 0.3 даёт True.

6. Итоговый вывод: False True True.

Почему это важно: В финансовых расчётах и работе с ценами часто используют Decimal, чтобы избежать ошибок float. Но при смешивании Decimal и float в сравнениях, сортировках или условиях результат может оказаться неожиданным: равенство может быть ложным, а max или min может выбрать не тот элемент. Правильно — приводить оба операнда к Decimal или к float явно и не полагаться на неявное преобразование.
3
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Python: задачки и вопросы
Развёрнутое пояснение:

1. MRO класса D(B, C): D, B, C, A.

2. D().f() печатает D и через super().f() делегирует следующему классу в MRO — B.

3. B.f печатает B и через super().f() делегирует следующему — C, а не A, потому что super() опирается на линейный MRO объекта, а не на прямого родителя.

4. C.f печатает C и через super().f() делегирует A.

5. A.f печатает A.

6. Итоговый вывод: DBCA.

Почему это важно: понимание MRO и super() нужно при проектировании миксинов и множественного наследования, иначе можно случайно пропустить ветку или вызвать метод дважды.
4
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Python: задачки и вопросы
Развёрнутое пояснение:

1. При первом обращении c.ports вызывается метод ports и возвращается список [80].

2. cached_property записывает этот объект в c.__dict__ под именем ports.

3. Вызов c.ports.append(443) изменяет именно тот список, который теперь лежит в кэше.

4. При повторном обращении c.ports cached_property находит ports в __dict__ и возвращает сохранённый объект [80, 443].

5. print выводит [80, 443].

Почему это важно: cached_property удобен для дорогих вычислений, но кэшированный объект остаётся общим для всех последующих обращений. Если метод возвращает изменяемую коллекцию и кто-то её мутирует, изменения застревают в кэше. В конфигах и синглтонах это приводит к «засорению» настроек между тестами или запросами: безопаснее возвращать неизменяемые копии или отделять изменяемое состояние от кэшированного свойства.
3
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Python: задачки и вопросы
Развёрнутое пояснение:

1. State — перечисление, член State.OK имеет значение ok, но сам является отдельным объектом Enum.

2. Функция check сравнивает строку ok с объектом State.OK оператором равенства.

3. У Enum операция равенства считает равными только члены одного и того же перечисления, поэтому сравнение со строкой возвращает False.

4. В результате print выводит False.

Почему это важно: при рефакторинге строковых констант в Enum часто забывают, что сравнение со строкой из JSON или БД перестаёт работать. Правильно сравнивать через State(raw) == State.OK или raw == State.OK.value. Это типичная ошибка в валидации API и конфигурации.
3
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Python: задачки и вопросы
Развёрнутое пояснение:

1. Создаётся пустой список queue.

2. defaultdict инициализируется фабрикой lambda: queue, которая при каждом обращении по отсутствующему ключу возвращает ссылку на этот же список.

3. tasks['api'] вызывает фабрику, возвращает queue и добавляет в него строку retry.

4. tasks['queue'] снова вызывает фабрику и возвращает тот же список queue, который уже содержит retry.

5. Поэтому print выводит ['retry'].

Почему это важно: такая ошибка возникает, когда разработчик хочет инициализировать значение изменяемым объектом и вместо конструктора list передаёт lambda, замкнутую на заранее созданный объект. В планировщиках задач, группировке событий по категориям или кэшировании результатов по ключам это приводит к тому, что разные ключи делят одно состояние. Правильный способ — передать list или функцию, создающую новый объект при каждом вызове, например defaultdict(list).
2
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Python: задачки и вопросы
Развёрнутое пояснение:

1. Создаётся словарь tags с ключами api и db.

2. Запускается цикл for key in tags, который получает итератор ключей словаря.

3. Итератор запоминает ожидаемое количество элементов на момент начала обхода.

4. При первом же ключе api условие срабатывает и вызывается tags.pop(key), удаляя элемент из словаря.

5. Словарь изменил размер во время итерации, поэтому при следующей попытке получить следующий ключ интерпретатор обнаруживает рассогласование и возбуждает RuntimeError: dictionary changed size during iteration.

6. print(tags) не выполняется, потому что исключение прерывает выполнение.

Почему это важно: такая ошибка часто возникает при фильтрации или очистке словарей состояния, кэша или метрик. Правильный способ — собрать ключи для удаления в отдельный список и удалять после цикла, либо создавать новый словарь через dict comprehension. Это позволяет избежать неожиданного падения на проде при обработке логов, конфигов или счётчиков.
1
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Python: задачки и вопросы
Развёрнутое пояснение:

1. Список logs содержит четыре кортежа: две записи api и две db, чередующиеся. 2. itertools.groupby не сортирует данные и не ищет все одинаковые ключи во всём списке: он формирует новую группу каждый раз, когда ключ очередного элемента отличается от ключа предыдущего. 3. Последовательность ключей в logs: api, db, api, db. Поэтому группы получаются такими: api с одной записью, db с одной записью, снова api с одной записью и снова db с одной записью. 4. В dict comprehension каждый ключ перезаписывается при повторном вхождении. Сначала 'api' получает список из одной ошибки, потом 'db' — один успех, затем 'api' зативается второй группой из одной успешной записи, и в конце 'db' перезаписывается группой с одной ошибкой. 5. В итоге groups['api'] — это список из одного кортежа [('api', 'ok')], а len от него равен 1.

Почему это важно: в аналитике логов и отчётах часто ожидают, что groupby сгруппирует все записи по ключу, как SQL GROUP BY, но в Python он работает только над отсортированными или уже упорядоченными данными. Если пропустить сортировку, группы дробятся, а при записи в словарь последняя группа затирает предыдущие с тем же ключом. Это приводит к тихой потере данных и неверным агрегатам.
2
⚡️ О!Хакатон возвращается — на кону миллион

Приглашаем Go- и Python-разработчиков, аналитиков и продакт-менеджеров на тревел-тех хакатон от Островка.

Вам предстоит решить одну из двух AI-задач в сфере тревел-теха и побороться за главный приз — 1 000 000 ₽.
Присоединиться к хакатону можно из любой точки мира. Участвуйте командой до пяти человек и выбирайте один из двух треков:

➡️ «О!дин запрос». Цель для junior-специалистов — создать AI-агента для путешествий и отелей.
➡️ «О!дин шаг до идеального отеля». Задача для специалистов уровней middle и senior — «переизобрести» опыт бронирования пользователя с помощью AI и новых интерфейсных механик.

📎 Регистрация открыта до 16 октября 2026 года. Стартуем 23 октября.

Скорее присоединяйтесь по ссылке!
Please open Telegram to view this post
VIEW IN TELEGRAM