TGViewer
Channel Public Channel
Python: задачки и вопросы

Python: задачки и вопросы

@quiz_python

Вопросы и задачки для подготовки к собеседованиям и прокачки навыков

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

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

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

Другие наши проекты: https://tprg.ru/media
Subscribers
6.94K
Photos
1.4K
Videos
1
Links
126

Showing posts older than #4810 · Back to latest

Older Posts 20 shown
Post #4809 342
Python: задачки и вопросы
Развёрнутое пояснение:

1. Вызывается dict.fromkeys с двумя аргументами: список ключей и один пустой список-значение.

2. Метод создаёт словарь, но не копирует значение для каждого ключа: api, db и cache получают ссылку на один и тот же список.

3. Обращение status['api'] возвращает этот общий список, и append('ok') изменяет его.

4. Поскольку db и cache указывают на тот же объект, их значения тоже становятся ['ok'].

5. print(status) выводит словарь, где каждый ключ содержит ['ok'].

Почему это важно: такая инициализация часто встречается при создании словарей статусов, группировок или конфигов с изменяемыми значениями. Вместо dict.fromkeys(keys, []) следует использовать dict comprehension {k: [] for k in keys} или collections.defaultdict(list), чтобы каждый ключ имел свой независимый список.
  • ✍ 5
Post #4805 323
Python: задачки и вопросы
Развёрнутое пояснение:

1. В классе OrderBatch определён атрибут items, который ссылается на пустой список. Это атрибут класса, а не экземпляра.

2. Создание a и b не создаёт новых списков, оба экземпляра через поиск атрибутов находят один общий список класса.

3. a.items.append(1) изменяет этот общий список, добавляя в него 1.

4. print(b.items) обращается к тому же атрибуту класса и выводит [1].

Почему это важно: class attributes часто используются как значения по умолчанию, а пустые изменяемые коллекции в них — классическая ошибка, приводящая к общему состоянию между экземплярами. Это проявляется в тестах, бэкенд-сервисах и кэшах, где экземпляры начинают неожиданно влиять друг на друга.
  • ✍ 1
Post #4803 361
Python: задачки и вопросы
Развёрнутое пояснение:

1. Создаётся список orders = [120, 80, 300, 50].

2. Создаётся генератор big = (o for o in orders if o > 100). Сам он ещё ничего не читает, а только запоминает источник и условие.

3. orders.append(400) изменяет исходный список: теперь orders = [120, 80, 300, 50, 400].

4. sum(big) начинает итерировать генератор. На этом шаге он проходит по текущему списку и отбирает элементы больше 100: 120, 300, 400.

5. Сумма отобранных элементов равна 820.

Почему это важно: ленивые итераторы не делают снимок данных в момент создания, а читают источник по мере потребления. В продакшене это встречается в ETL-пайплайнах, потоковой обработке и работе с большими файлами, где данные могут меняться между созданием пайплайна и его запуском. Понимание этого помогает избежать неожиданных результатов при обработке заказов, логов или метрик.
  • ✍ 2
Post #4798 401
Python: задачки и вопросы
Развёрнутое пояснение:

1. Вызов save(10) входит в функцию и сразу попадает в блок try.

2. Внутри try выполняется value / 0, что порождает исключение ZeroDivisionError.

3. Управление переходит в блок except ZeroDivisionError, который готовится вернуть строку "fail".

4. Перед тем как функция завершится, Python обязательно выполняет блок finally, независимо от того, было ли исключение.

5. В finally встречается собственный return "cleanup"; return в finally заменяет любой ранее подготовленный результат или даже не обработанное исключение.

6. Поэтому save(10) возвращает "cleanup", и print выводит cleanup.

Почему это важно: return в finally перекрывает не только обычные значения, но и исключения, что легко превращает функцию очистки ресурсов в источник молчаливых потерь ошибок. В реальном коде finally стоит использовать только для освобождения ресурсов, закрытия соединений и снятия флагов, а итоговый результат или статус ошибки возвращать из try/except.
  • ✍ 2
Post #4796 415
Python: задачки и вопросы
Развёрнутое пояснение:

1. Создаётся кортеж route = ('start',).

2. Вызов tag(route) передаёт ссылку на этот кортеж в параметр path.

3. Внутри tag выполняется path += ('end',): так как tuple неизменяемый, Python не может расширить существующий объект, а создаёт новый кортеж ('start', 'end') и присваивает его локальной переменной path.

4. Переменная route в вызывающем коде продолжает ссылаться на исходный кортеж ('start',).

5. print(route) выводит ('start',).

Почему это важно: с неизменяемыми типами (tuple, str, int) оператор += никогда не меняет исходный объект, он лишь создаёт новое значение и переприсваивает локальную ссылку. Поэтому функция, которая должна «дополнить» переданный неизменяемый объект, должна явно вернуть результат, иначе вызывающий код не увидит изменений. Это частая ошибка при работе с путями, идентификаторами и конфигурационными ключами.
  • ✍ 1
Post #4793 442
Python: задачки и вопросы
Развёрнутое пояснение:

1. Вызов fetch() входит в блок try. 2. В try возникает исключение ValueError('fail'). 3. Перед завершением функции выполняется блок finally. 4. В finally встречается return 'ok', который подавляет исключение и возвращает это значение. 5. print(fetch()) печатает ok.

Почему это важно: return, break или continue в finally могут скрыть ошибки, поэтому cleanup-код не должен возвращать значений или прерывать поток управления.
  • ✍ 5
Post #4791 454
Python: задачки и вопросы
Развёрнутое пояснение:

1. В main сначала вызывается create_task(f(2)), поэтому задача для f(2) встаёт в очередь цикла событий первой.

2. Затем вызывается create_task(f(1)), и задача для f(1) становится второй в очереди.

3. await t1 отдаёт управление циклу событий, который начинает выполнять отложенные задачи в порядке их постановки.

4. Сначала запускается f(2): она печатает 2, затем await asyncio.sleep(0) приостанавливает её.

5. Пока f(2) ждёт, цикл переключается на f(1), печатает 1 и тоже засыпает на 0.

6. Когда sleep(0) завершается, задачи просыпаются в том же порядке: f(2) печатает 12, затем f(1) печатает 11.

7. await t1 и await t2 завершаются, так как обе задачи уже выполнены. В stdout оказывается 2, 1, 12, 11.

Почему это важно: в асинхронных сервисах create_task лишь планирует задачу, а не запускает её мгновенно. Порядок выполнения определяется очередью событий, поэтому await в конце не меняет порядок, заданный при создании задач. Это помогает избежать неожиданного порядка вызовов при инициализации ресурсов, логировании или конкурентной обработке событий.
  • ✍ 4
Post #4787 442
Python: задачки и вопросы
Развёрнутое пояснение:

1. Определяется класс Field с методами __set__ и __get__, что делает его дескриптором данных.

2. Класс Record получает атрибут класса value, равный экземпляру Field.

3. Создаётся r = Record().

4. Присваивание r.value = 3 вызывает дескрипторный метод __set__, который записывает в r._val значение 3 * 10, то есть 30.

5. Прямая запись r.__dict__["value"] = 9 помещает 9 в словарь экземпляра, но не вызывает дескриптор и не заменяет атрибут класса.

6. При чтении r.value правило поиска атрибутов в Python сначала проверяет дескриптор данных в классе; он находит value = Field() и вызывает его __get__, возвращающий r._val, равное 30.

7. Значение 9 из __dict__ остаётся недоступным через обычный доступ r.value, пока дескриптор с __set__ существует.

Почему это важно: В ORM, валидаторах и property с setter часто скрывают хранение значения за дескрипторами. Ошибка возникает, когда разработчик пишет obj.__dict__["field"] =... или сериализатор заполняет словарь напрямую, ожидая, что это эквивалентно obj.field =.... В действительности дескриптор данных переопределяет чтение, поэтому тесты могут показать одно значение, а обычный доступ — другое. Понимание приоритета дескрипторов помогает избежать рассинхронизации между внутренним хранилищем и публичным интерфейсом.
  • ✍ 3
Post #4785 444
Python: задачки и вопросы
Развёрнутое пояснение:

1. Создаётся u с id=1; его __hash__ возвращает 1.

2. Словарь d помещает пару u: 'a' в корзину для хэша 1.

3.
u.id меняется на 2; сам объект u всё ещё лежит в корзине 1, потому что словарь не пересчитывает хэш.

4. d.get(User(2)) вычисляет хэш нового объекта — 2 — и ищет в корзине 2.

5. В корзине 2 ничего нет, поэтому возвращается None.

Почему это важно: ключи dict и элементы set должны быть неизменяемыми относительно величины, участвующей в __hash__. Если объект-ключ мутирует, он остаётся в старой корзине, и поиск по новому хэшу его не найдёт. Это приводит к утечкам в кэшах, потере данных в индексах и нестабильным тестам при использовании изменяемых сущностей в качестве ключей.
  • ✍ 4
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →