Python: задачки и вопросы
6.87K subscribers
1.35K photos
1 video
1 file
129 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️⃣Объект p принадлежит классу Price. Метод __repr__ возвращает строку DEBUG, а __format__ — PUBLIC.

2️⃣В выражении f"{p}" Python вызывает p.__format__(""). Пустая строка означает, что после двоеточия не задан формат. Наш метод возвращает PUBLIC.

3️⃣В выражении f"{p!r}" сначала вызывается repr(p). Получается строка DEBUG, после чего форматирование применяется уже к этой строке. Метод Price.__format__ здесь не вызывается.

4️⃣Оба результата передаются в print, который разделяет их пробелом. Итоговый вывод: PUBLIC DEBUG.

Почему это важно
Класс может по-разному представлять объект в отчёте и при отладке. Например, __format__ выводит цену с валютой, а __repr__ показывает данные для диагностики. Добавление !r меняет путь преобразования, поэтому его нельзя считать просто декоративной пометкой.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
✍1
Разбор по шагам

1️⃣В span записана длительность 25 часов и 30 секунд. Это 1 сутки, 1 час и 30 секунд.

2️⃣Объект timedelta хранит длительность в днях, секундах и микросекундах. Здесь span.days равен 1, а span.seconds содержит оставшиеся после выделения полных суток секунды: 3600 + 30 = 3630.

3️⃣Метод total_seconds() учитывает всю длительность вместе с днями: 25 × 3600 + 30 = 90030. Он возвращает число с плавающей точкой — 90030.0.

4️⃣Поэтому print выводит 3630 90030.0.

Почему это важно
Для расчёта времени работы сервиса, таймаута или длительности задания используйте total_seconds(). Если взять только seconds, полные сутки не попадут в расчёт: в этом примере из длительности потеряются 24 часа.
Please open Telegram to view this post
VIEW IN TELEGRAM
Почему разработчик планирует отдавать больше задач Claude

Винсент Шмальбах описал план перераспределить расходы на ИИ: больше работы отдавать Claude, а Codex сохранить для части задач.

К решению его подтолкнули затяжные сессии. По наблюдениям автора, агент иногда часами продолжал проверки и добавлял соседние задачи. Квота расходовалась, а момент, когда можно принять результат и двигаться дальше, было трудно предсказать.

В личном разборе Шмальбах связывает эти эпизоды с условиями подписки и затратами на собственные проекты.

#ии #инструменты

🐸 Библиотека ИИ для айтишников
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Порядок вывода

1️⃣В ids два идентификатора: a и b. В states только один статус: ok. Вызов zip создаёт итератор, который будет получать элементы по мере обхода.

2️⃣При первом шаге цикла элементы есть в обоих списках. zip выдаёт пару a и ok, тело цикла выполняется и печатает a ok.

3️⃣На следующем шаге в ids ещё есть b, а states уже закончился. Из-за strict=True возникает ValueError. Вторую пару zip не выдаёт, тело цикла для b не выполняется.

4️⃣Исключение перехватывает блок except, который печатает mismatch. Получаются две строки: a ok, затем mismatch.

Почему это важно
Строгий режим помогает обнаружить несовпадение числа записей, но не проверяет весь вход заранее. Если тело цикла сохраняет данные или отправляет запросы, часть работы может быть выполнена до ошибки. Для готовых списков можно отдельно проверить длины до начала обработки.
Please open Telegram to view this post
VIEW IN TELEGRAM
✍1
Please open Telegram to view this post
VIEW IN TELEGRAM
Разбор по шагам

1️⃣Базовый адрес https://example.com/api/ содержит схему https, хост example.com и путь /api/.

2️⃣Второй аргумент urljoin — /users. Начальный / задаёт путь от корня сайта.

3️⃣Функция сохраняет схему и хост базового адреса, а путь /api/ заменяет на /users.

4️⃣На экран выводится https://example.com/users. Если бы второй аргумент был "users", результатом стал бы https://example.com/api/users.

Почему это важно
При сборке адресов API начальный / может увести запрос из нужного раздела сайта. Если базовый адрес уже заканчивается на /api/, путь "users" сохранит этот раздел, а "/users" отправит запрос к корню.
Please open Telegram to view this post
VIEW IN TELEGRAM
✍2
Please open Telegram to view this post
VIEW IN TELEGRAM
Как меняется буфер

1️⃣В data лежат байты AB. Вызов memoryview(data) создаёт представление того же буфера, не копию данных.

2️⃣Присваивание data[0] = ord("Z") заменяет первый байт без изменения размера. Представление видит эту запись, поэтому первый print выводит b'ZB'.

3️⃣Вызов append пытается увеличить bytearray. Пока view активно, изменение размера запрещено: возникает BufferError, обработчик печатает blocked. Байт C не добавляется.

4️⃣Вызов view.release() освобождает представление. Теперь ограничение на изменение размера, связанное с этим view, снято. Сам bytearray при этом остаётся.

5️⃣Второй append успешно добавляет C. Последний print выводит b'ZBC'. Все три строки: b'ZB', blocked, b'ZBC'.

Почему это важно
Представления помогают обрабатывать бинарные пакеты без копирования. Пока такое представление активно, можно заменять байты внутри буфера, но нельзя расширять bytearray. Перед расширением нужно освободить все активные представления этого буфера.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Что успевает выполниться

1️⃣Класс Limit определяет метод __int__, который возвращает целое число 2. Экземпляр этого класса сохраняется в limit.

2️⃣Вызов int(limit) использует __int__. Преобразование успешно, поэтому первый print выводит 2.

3️⃣Во втором вызове сначала вычисляется аргумент: срез строки "abcdef" с границей limit. Для такого объекта Python требует метод __index__, возвращающий целое число. Одного __int__ недостаточно.

4️⃣У Limit нет __index__, поэтому возникает TypeError. Второй print не вызывается: в обычном выводе остаётся только 2, а выполнение завершается с ошибкой.

Почему это важно
Вызов int(obj) разрешает объекту преобразоваться в число, но не делает его автоматически допустимым индексом. При создании собственного целочисленного типа для срезов или range нужен __index__. Если же лимит нужно явно преобразовать, это можно сделать в месте использования: "abcdef"[:int(limit)] даст ab.
Please open Telegram to view this post
VIEW IN TELEGRAM
✍1
Please open Telegram to view this post
VIEW IN TELEGRAM
Что меняют скобки

1️⃣Строка text содержит три имени, разделённые двоеточиями. Оба шаблона находят те же два разделителя.

2️⃣В первом вызове шаблон : не содержит групп. re.split возвращает только части между разделителями: ['api', 'db', 'auth'].

3️⃣Во втором вызове скобки создают захватывающую группу. Её совпадения тоже входят в результат, между соседними частями текста.

4️⃣Поэтому второй список — ['api', ':', 'db', ':', 'auth']. Двоеточия не исчезли: их попросили захватить.

Почему это важно
Так можно разбить выражение на токены и сохранить операторы или пунктуацию. Если скобки нужны лишь для группировки шаблона, используйте незахватывающую группу (?:...), чтобы разделители не добавлялись в результат.
Please open Telegram to view this post
VIEW IN TELEGRAM
✍1
Please open Telegram to view this post
VIEW IN TELEGRAM
Поиск и вставка

1️⃣Записи rows упорядочены по первому числу. Функция key возвращает это число из каждой строки.

2️⃣bisect_left применяет key к элементам rows, но не к аргументу new. Поэтому при поиске сравниваются число и кортеж. Возникает TypeError, обработчик печатает search failed.

3️⃣insort_left при поиске позиции вычисляет key(new), получая 15. Число попадает между 10 и 20, и вставка успешно находит индекс 1.

4️⃣В список вставляется исходный кортеж, не число 15. Результат: [(10, 'a'), (15, 'b'), (20, 'c')].

Почему это важно
При ручном поиске позиции передавайте значение в пространстве ключей: bisect_left(rows, key(new), key=key). При вставке через insort передают целую запись. Похожие параметры этих функций не означают одинаковую обработку искомого объекта.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Два момента применения точности

1️⃣В локальном контексте ctx.prec = 3 задаёт три значащие цифры для операций Decimal. Это не число знаков после запятой.

2️⃣Decimal("1.2345") точно сохраняет переданную десятичную строку. Конструктор не обрезает её по prec, поэтому первый print выводит 1.2345.

3️⃣Выражение +price выполняет операцию Decimal в текущем контексте. При точности 3 результат округляется до 1.23.

4️⃣Второй print выводит 1.23. Исходный price не изменился: унарный плюс вернул новое значение.

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