Python Quiz
489 subscribers
867 photos
727 links
🎓 Python-викторины для программистов.
Каждый день новая задача, разбор и неожиданные фишки языка.
Download Telegram
Python Quiz
Что выведет этот код? ⚙️💻
Чему учит: отличать dict.get и dict.setdefault и замечать их побочные эффекты при инициализации ключей.
Зачем важно: помогает писать предсказуемый код и не ловить сюрпризы на собеседовании.
setdefault создаёт ключ со значением по умолчанию и возвращает его; get сам по себе ключ не со…
Python Quiz
Что выведет этот код? 🧠🤔
Чему учит: разница между тождественностью объекта (is) и равенством значений (==), и что namedtuple не меняется на месте.
Зачем: пригодится на собеседованиях и чтобы не терять баги из‑за ожиданий мутабельности. 😺
_replace создаёт новый экземпляр; is проверяет, один ли это объект, == …
Что выведет этот код? ⚙️🐍
Anonymous Quiz
100%
0
0%
1
0%
2
0%
Ошибка во время выполнения
Python Quiz
Что выведет этот код? ⚙️🐍
Чему учит: поведение __eq__ и __hash__ при добавлении объектов в set.
Зачем важно: нужно для корректной дедупликации, проектирования типов и на собеседованиях про хэш‑контракт.
Подсказка: set сначала смотрит __hash__, затем вызывает __eq__ для объектов с одинаковым хэшем.
Python Quiz
Что выведет этот код? 🧠🤔
Учит: поведение генераторов, состояние итератора после next() и как zip обрабатывает один и тот же итератор.
Зачем важно: помогает не допускать едва заметных багов в проде и блеснуть на собеседовании знанием итераторов.
next(gen) сдвигает итератор на один; zip(gen, gen) берёт элемент…
Что выведет этот код? 💡🧠
Anonymous Quiz
100%
07
0%
7
0%
Будет ValueError
0%
Будет SyntaxError
Python Quiz
Что выведет этот код? 💡🧠
Чему учит: f‑строки с динамической шириной — как подставлять спецификатор формата через { } и контролировать заполнение.
Зачем важно: полезно для аккуратного вывода чисел в логах/отчётах и на собеседованиях, где проверяют синтаксис. 😺
'0' перед шириной — символ заполнителя нулями; {w…
JIT в Python могут выпилить — и не потому что он глючит

Полгода никто не чесался — JIT спокойно жил в main с 3.13, разгонял x86-64/Linux в среднем на 8-9% и должен был стать одной из витрин 3.15 (тот уже во freeze, релиз в октябре). А 5 июня Steering Council внезапно нажал стоп.

Причина не техническая. Всё это держится на PEP 744, а он informational, не standards-track — то есть юридически никого ни к чему не обязывает: ни к поддержке, ни к метрикам успеха, ни к обещаниям совместимости. Совет сам признал: "мы не были достаточно строги к процессу для изменения такого масштаба".

Дали полгода: либо нормальный normative PEP с критериями принятия, либо код едет из main. Баги и security чинят как обычно, новые фичи — заморожены. Томас Воутерс из совета: "we're not unreasonable, but we do want this to be taken seriously" — не расстрельный дедлайн, но и не формальность для галочки.

Мне это скорее нравится, хоть и с опозданием. Три релиза фича жила без единого письменного обязательства на случай, если что-то пойдёт не так. Спохватились бы раньше — меньше народу сейчас зависело бы от undocumented behavior.
👍1
В comprehension наконец завезли распаковку через *

Все путаются в [x for row in matrix for x in row] — кажется, что for идут как во вложенном цикле, а на деле наоборот, второй for относится к первому. Классический баг на собеседованиях.

PEP 798 чинит это через *: [*row for row in matrix] — то же самое, но без риска перепутать порядок. Работает и для {*row for row in matrix}, и для словарей через **.

Забавная деталь из самого PEP: авторов натолкнул письменный экзамен по Python — студенты в ответах уже писали такую звёздочку, будучи уверены, что она существует. Не существовала — до сих пор.

Фича заморожена в 3.15.0b1, релиз в октябре. Двойной for никуда не денется, но хотя бы будет чем его заменить, когда не хочешь гадать про порядок циклов.
Ваш free-threaded питон может тихо врать про GIL

Поставил 3.14.0t (free-threaded сборку), жду параллелизма — а профиль как будто однопоточный.

Оказалось, это норм поведение, просто нигде не орёт об этом. Любое C-расширение, не помеченное как поддерживающее free-threading, при импорте тихо включает GIL обратно. Без варнинга, без ошибки — просто твой параллелизм молча схлопывается в обычный GIL-режим.

Проверяется одной строкой после всех импортов:

python3.14 -c "import sys; print(sys._is_gil_enabled())"

True после импорта нужных тебе либ — значит что-то из зависимостей откатило GIL обратно, и весь выигрыш от free-threaded сборки ты потерял, просто об этом не узнал.

Есть ещё жёсткий вариант — PYTHON_GIL=0 или -X gil=0: тогда откат запрещён, и несовместимое расширение уронит процесс вместо тихого отката. Для CI это честнее, чем молчаливая деградация.

Перед тем как постить в чат бенчмарки с линейным ускорением на 3.14t — сначала эта проверка, потом бенчмарк.
Что выведет этот код с lazy import в Python 3.15?

В 3.15 beta 4 подвезли lazy import (PEP 810) — модуль реально не грузится, пока не тронешь его атрибут. Звучит как мелочь, а ломает интуицию с ходу.

Взял классику: import this печатает дзен прямо при загрузке модуля, это все знают. Обернул в lazy import и написал zen = this. Был уверен, что присваивание — это уже «использование». Не угадал.

Прогони в голове, без REPL. Порядок печати — в опросе.
В Django чужая сессия могла прилететь вам в общем кэше

Django тихо чинит баг, из-за которого чужая сессионная кука могла закэшироваться и уйти следующему юзеру.

UpdateCacheMiddleware и cache_page() пропускали ответ с Set-Cookie в кэш, если проверяли только один случай: запрос пришёл вообще без кук. Логика была «нет кук на входе — значит и Set-Cookie можно смело кэшировать». Стоило браузеру принести любую левую куку — тему, язык, A/B-флаг — и проверка молча выключалась. Сессионный Set-Cookie улетал в общий кэш как ни в чём не бывало.

Дальше классика cache poisoning: если перед Django стоит Redis, Memcached или CDN — следующий, кто попал в тот же ключ кэша, мог получить в ответе чужую сессию.

Бесит не сама дыра, а то, как она написана — условие «если у запроса нет X» почти всегда придумано под один тестовый сценарий, а не под реальный трафик, где у половины пользователей уже висит кука с языком интерфейса или темой.

Пофиксили в 6.0.7 и 5.2.16 (заодно и в 6.1-бете), CVE-2026-48588, severity формально low — нужны shared cache и Vary: Cookie вместе. Но именно так у многих и настроено.

Если у вас cache_page или UpdateCacheMiddleware рядом с сессиями — это тот случай, когда апдейт не терпит «на следующем спринте».
Python откатил архитектуру сборщика мусора прямо в патч-релизе

Python 3.14.0 в октябре сменил сборщик мусора — с generational на incremental, обещали паузы на больших кучах короче на порядок. В 3.14.5 в мае это просто откатили назад. Патч-релиз отменяет архитектурное решение целого мажора — в CPython такое почти не бывает.

Что пошло не так: на долгоживущих процессах (веб-серверы, пайплайны) резидентная память росла без остановки. По разбору pydevtools, счётчик инкрементальной работы мог уходить в минус — и полный проход сборщика попросту не запускался: в одном из кейсов первый full collection случился только на 20 000-й итерации, а в устойчивом состоянии в памяти висело больше 90 тысяч непрочищенных циклов.

Core team не стала ждать плановый 3.14.6 — ускорили релиз и откатили incremental GC сразу в 3.14 и 3.15, вернув generational из 3.13.

Смущает не сам баг — memory-менеджмент штука тонкая. Смущает то, что фичу пять месяцев гоняли через альфы, беты и rc — и всё равно поймали только когда реальный прод начал жаловаться на RSS. Если вы успели обновиться до 3.14.0–3.14.4 и мониторили память — вы только что бесплатно побетатестили GC для всего коммьюнити.

🔗 discuss.python.org, pydevtools.com
Гитхаб был чистый. Пакет — нет

В mrmustard 0.7.4 — квантовой библиотеке Xanadu на PyPI — три дня назад нашли стилер. Тащит с диска SSH-ключи, AWS- и Kubernetes-креды и ставит три способа зацепиться в системе на будущее.

Но бесит не сам стилер, а то, как его спрятали.

У версии 0.7.4 нет ни тега, ни релиза, ни коммита в GitHub-репозитории. Открываешь исходники на гитхабе — там всё чисто, ревью ничего не найдёт. Вредонос добавили только в артефакт, который улетает через pip install: угнали токен CI из аккаунта мейнтейнера (это был ziofil, автор проекта) и залили пакет в PyPI напрямую, мимо обычного пайплайна.

Отдельная деталь для тех, кто вообще думает про такие атаки: пейлоад сначала проверяет, что он не в CI и не в контейнере, и только потом стартует. Целились именно в ноутбуки разрабов и исследователей, а не в одноразовые раннеры.

После такого фраза «да я гитхаб пролистал, там нормально» перестаёт что-либо значить. Гитхаб и то, что реально прилетает по pip install, — два разных артефакта, и связывает их только честность мейнтейнера в момент публикации. Если пиньте пакеты по хэшу wheel — вот ровно тот случай, когда это спасает, а не паранойя.

Нашёл всё не Xanadu, а сторонний исследователь из Aikido Security. PyPI пакет после этого отправил в карантин.

🔗 stepsecurity.io, safedep.io