Что выведет этот код? ⚙️💻
Anonymous Quiz
0%
Вывод: 3 3
0%
Вывод: None 3
0%
Вывод: 3 KeyError
0%
Вывод: KeyError 3
Python Quiz
Что выведет этот код? ⚙️💻
Чему учит: отличать dict.get и dict.setdefault и замечать их побочные эффекты при инициализации ключей.
Зачем важно: помогает писать предсказуемый код и не ловить сюрпризы на собеседовании.
setdefault создаёт ключ со значением по умолчанию и возвращает его; get сам по себе ключ не со…
Зачем важно: помогает писать предсказуемый код и не ловить сюрпризы на собеседовании.
Что выведет этот код? 🧠🤔
Anonymous Quiz
0%
Выведет: True 2
0%
Выведет: True 1
100%
Выведет: False 1
0%
Выведет: False 2
Python Quiz
Что выведет этот код? 🧠🤔
Чему учит: разница между тождественностью объекта (is) и равенством значений (==), и что namedtuple не меняется на месте.
Зачем: пригодится на собеседованиях и чтобы не терять баги из‑за ожиданий мутабельности. 😺
_replace создаёт новый экземпляр; is проверяет, один ли это объект, == …
Зачем: пригодится на собеседованиях и чтобы не терять баги из‑за ожиданий мутабельности. 😺
Python Quiz
Что выведет этот код? ⚙️🐍
Чему учит: поведение __eq__ и __hash__ при добавлении объектов в set.
Зачем важно: нужно для корректной дедупликации, проектирования типов и на собеседованиях про хэш‑контракт.
Подсказка:set сначала смотрит __hash__, затем вызывает __eq__ для объектов с одинаковым хэшем.
Зачем важно: нужно для корректной дедупликации, проектирования типов и на собеседованиях про хэш‑контракт.
Подсказка:
Что выведет этот код? 🧠🤔
Anonymous Quiz
0%
[(1, 2), (3, 4)]
50%
[(0, 1), (2, 3), (4, 5)]
50%
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
0%
[(1, 2), (2, 3), (3, 4)]
Python Quiz
Что выведет этот код? 🧠🤔
Учит: поведение генераторов, состояние итератора после next() и как zip обрабатывает один и тот же итератор.
Зачем важно: помогает не допускать едва заметных багов в проде и блеснуть на собеседовании знанием итераторов.
next(gen) сдвигает итератор на один; zip(gen, gen) берёт элемент…
Зачем важно: помогает не допускать едва заметных багов в проде и блеснуть на собеседовании знанием итераторов.
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.
Полгода никто не чесался — 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 наконец завезли распаковку через *
Все путаются в
PEP 798 чинит это через
Забавная деталь из самого PEP: авторов натолкнул письменный экзамен по Python — студенты в ответах уже писали такую звёздочку, будучи уверены, что она существует. Не существовала — до сих пор.
Фича заморожена в 3.15.0b1, релиз в октябре. Двойной for никуда не денется, но хотя бы будет чем его заменить, когда не хочешь гадать про порядок циклов.
Все путаются в
[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-режим.
Проверяется одной строкой после всех импортов:
Есть ещё жёсткий вариант —
Перед тем как постить в чат бенчмарки с линейным ускорением на 3.14t — сначала эта проверка, потом бенчмарк.
Поставил 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 подвезли
Взял классику:
Прогони в голове, без REPL. Порядок печати — в опросе.
В 3.15 beta 4 подвезли
lazy import (PEP 810) — модуль реально не грузится, пока не тронешь его атрибут. Звучит как мелочь, а ломает интуицию с ходу.Взял классику:
import this печатает дзен прямо при загрузке модуля, это все знают. Обернул в lazy import и написал zen = this. Был уверен, что присваивание — это уже «использование». Не угадал.Прогони в голове, без REPL. Порядок печати — в опросе.
Python Quiz
Что выведет этот код с lazy import в Python 3.15? В 3.15 beta 4 подвезли lazy import (PEP 810) — модуль реально не грузится, пока не тронешь его атрибут. Звучит как мелочь, а ломает интуицию с ходу. Взял классику: import this печатает дзен прямо при загрузке…
В каком порядке напечатается вывод?
Final Results
100%
start → bound → zen → end
0%
zen → start → bound → end
0%
start → zen → bound → end
0%
start → bound → end, zen не печатается
В Django чужая сессия могла прилететь вам в общем кэше
Django тихо чинит баг, из-за которого чужая сессионная кука могла закэшироваться и уйти следующему юзеру.
Дальше классика cache poisoning: если перед Django стоит Redis, Memcached или CDN — следующий, кто попал в тот же ключ кэша, мог получить в ответе чужую сессию.
Бесит не сама дыра, а то, как она написана — условие «если у запроса нет X» почти всегда придумано под один тестовый сценарий, а не под реальный трафик, где у половины пользователей уже висит кука с языком интерфейса или темой.
Пофиксили в 6.0.7 и 5.2.16 (заодно и в 6.1-бете), CVE-2026-48588, severity формально low — нужны shared cache и
Если у вас
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 рядом с сессиями — это тот случай, когда апдейт не терпит «на следующем спринте».