Дескрипторы — та часть объектной модели Python, которую большинство использует каждый день, не зная названия. Официальное руководство Раймонда Хеттингера объясняет её по шагам и остаётся живой документацией, а не архивом.
Протокол состоит из трёх методов:
🔘
🔘 обычная функция становится связанным методом ровно потому, что функция — тоже дескриптор;
🔘
🔘 разница между дескрипторами с записью и без определяет, кто победит: дескриптор или словарь экземпляра;
🔘 на этом же построены
Практическая часть — готовый класс
@zen_of_python
Протокол состоит из трёх методов:
__get__, __set__ и __delete__. Класс, реализующий их, перехватывает доступ к атрибуту. Из этого собрано больше, чем кажется:property, staticmethod, classmethod и super() — всё это дескрипторы, и в руководстве показаны их упрощённые реализации на Python;__set_name__ позволяет дескриптору узнать имя атрибута, под которым его объявили;__slots__ и модели в ORM.Практическая часть — готовый класс
Validator и валидаторы OneOf, Number и String: проверка типов и диапазонов при присваивании, без единой строчки проверок в коде, который этими полями пользуется.@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
Почему
Антонио Куни разобрал по шагам, что происходит при обращении к атрибуту — от байткода до кода CPython. Порядок поиска на картинке.
Из него сразу объясняется несколько загадок. Дескриптор данных, то есть объект с
Там же видно, откуда берётся связанный метод: обычная функция — это дескриптор без записи, и
У классов поиск устроен иначе: сначала дескрипторы данных метакласса, потом полный проход по порядку разрешения методов.
Автор берёт CPython 3.12.11: в 3.13 этот код усложнён оптимизациями.
@zen_of_python
obj.prop вызывает функцию, а C.prop возвращает объект, и откуда метод знает про selfАнтонио Куни разобрал по шагам, что происходит при обращении к атрибуту — от байткода до кода CPython. Порядок поиска на картинке.
Из него сразу объясняется несколько загадок. Дескриптор данных, то есть объект с
__get__ и __set__, проверяется раньше словаря экземпляра — поэтому property не перекрыть, положив одноимённый ключ в obj.__dict__. И property остаётся дескриптором данных, даже когда сеттера нет: он определяет __set__ и сам поднимает AttributeError.Там же видно, откуда берётся связанный метод: обычная функция — это дескриптор без записи, и
obj.meth разворачивается в C.meth.__get__(obj, C).У классов поиск устроен иначе: сначала дескрипторы данных метакласса, потом полный проход по порядку разрешения методов.
Автор берёт CPython 3.12.11: в 3.13 этот код усложнён оптимизациями.
@zen_of_python
❤2
Ромен Моротти разобрал профилировщиком, куда уходит время pip install, и довёл установку до двукратного ускорения, а скачивание — до семикратного. На картинке тот самый профиль в SnakeViz.
🔘 создание каталогов при установке одного пакета вызывалось 14 425 раз; осталось 1 538;
🔘 набор поддерживаемых меток колёс, 889 значений, пересчитывался заново для каждого пакета — кэширование дало около 17 процентов;
🔘 функция получения установленного пакета вела себя квадратично: на трёхстах пакетах итоговая сводка занимала треть времени;
🔘 распаковка читала архив мелкими кусками, блок в 1 мебибайт дал ещё около 10 процентов;
🔘 библиотека запросов тянула сеть кусками по 10 килобайт: переход к 256 килобайтам поднял скорость с 60 до 260 мегабайт в секунду;
🔘 отрисовка полосы прогресса съедала до 30 процентов времени загрузки.
Поучительна и судьба правок: исправление двойного сброса на диск, а это 7 процентов, не приняли из-за разного поведения файловых систем.
@zen_of_python
Поучительна и судьба правок: исправление двойного сброса на диск, а это 7 процентов, не приняли из-за разного поведения файловых систем.
@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Тесты бэкенда PyPI шли 163 секунды, стали 30 — при том что самих тестов стало больше: было около 3900, стало больше 4700.
Алексис Шалланд описал, что именно сделали. Порядок действий подойдёт любому медленному набору на pytest:
🔘 распараллелить через
🔘 чтобы процессы не топтали данные друг друга, фикстура базы берёт идентификатор рабочего процесса: у каждого своя база
🔘 для покрытия в параллельном режиме добавить
🔘 переключить измерение покрытия на механизм наблюдения из Python 3.12 через
🔘 указать
🔘 прогнать
Логику тестов при этом не меняли и покрытие не снижали.
@zen_of_python
Алексис Шалланд описал, что именно сделали. Порядок действий подойдёт любому медленному набору на pytest:
pytest-xdist с --numprocesses=auto; на 32 ядрах замер упал с 191 до 63 секунд;tests-{worker_id};sitecustomize.py с coverage.process_startup();COVERAGE_CORE=sysmon — с 58 до 27 секунд;testpaths: сбор тестов ускорился с 7,84 до 2,60 секунды;python -X importtime и выкинуть лишний импорт.Логику тестов при этом не меняли и покрытие не снижали.
@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤2
Правила типизации Python рассыпаны по десяткам PEP и страницам документации, а два разных проверяющих на одном коде дают разные ответы. Андрей Наку и Дорел Лукану попробовали собрать это в одну модель.
Отправная точка: каждый тип в Python представлен классом, класс задаёт абстрактный тип данных, а такой тип описывается в терминах экзистенциальных типов. Дальше авторы разводят три отношения, которые в разговорах обычно смешивают: быть подклассом, быть экземпляром объекта и быть экземпляром типа.
По дороге разбираются вещи, полезные и без формализма:
🔘 почему объединение типов и классов в Python 2.2 и переход к порядку разрешения методов C3 в 2.3 определили нынешнее поведение множественного наследования;
🔘 чем
🔘 как устроен слой метаклассов, где класс одновременно и шаблон для экземпляров, и обычное значение;
🔘 чем расходятся
Авторы честно ограничивают область: формализм описывает программы, где типы не меняются на ходу, а подтипизация и динамика оставлены на будущее.
@zen_of_python
Отправная точка: каждый тип в Python представлен классом, класс задаёт абстрактный тип данных, а такой тип описывается в терминах экзистенциальных типов. Дальше авторы разводят три отношения, которые в разговорах обычно смешивают: быть подклассом, быть экземпляром объекта и быть экземпляром типа.
По дороге разбираются вещи, полезные и без формализма:
Protocol отличается от абстрактного базового класса и где проходит граница между проверкой во время выполнения и статической;mypy и Pyright: первый сильнее опирается на аннотации и знание стандартной библиотеки, второй заточен под быстрый статический анализ.Авторы честно ограничивают область: формализм описывает программы, где типы не меняются на ходу, а подтипизация и динамика оставлены на будущее.
@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
В асинхронных генераторах появится
Сейчас делегировать другому асинхронному генератору можно только циклом
🔘
🔘
🔘 компилятор перестаёт выдавать
PEP 525 в 2016 году отказался от этого из-за сложности реализации; автор нового PEP Питер Бирма считает, что нынешний код CPython это позволяет, и приложил рабочую реализацию. Вариант
@zen_of_python
yield from. PEP 828 принят 3 августа, целевая версия — Python 3.16.Сейчас делегировать другому асинхронному генератору можно только циклом
async for с ручным yield. Это прячет намерение, ломает связь asend(), athrow() и aclose() с вызывающей стороной и не даёт вернуть значение: приходится бросать исключение.result = yield from agenerator() делегирует aiter(), anext(), asend(), athrow() и aclose();return 3 внутри асинхронного генератора становится законным, значение приезжает через новый атрибут StopAsyncIteration.value, по аналогии со StopIteration.value;SyntaxError на return с значением и yield from в async def с yield.PEP 525 в 2016 году отказался от этого из-за сложности реализации; автор нового PEP Питер Бирма считает, что нынешний код CPython это позволяет, и приложил рабочую реализацию. Вариант
async yield from отвергли ради симметрии с обычными генераторами, и в тексте прямо сказано, что переключение контекста без явного await — спорное место.@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Уже завтра вечером в 19:00 по МСК приходите на открытое онлайн-собеседование, чтобы посмотреть на настоящее интервью на Middle Python-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Python-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходите в нашего бота, чтобы получить ссылку на эфир → @shortcut_py_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
Starlette научился сжимать большие ответы вне event loop. В релизах с 1.4.0 по 1.6.0, вышедших 5 и 8 августа, переделан
🔘 тела от 128 КиБ сжимаются в рабочем потоке, а не в цикле событий; вместо
🔘 потоковые ответы получают flush на каждом чанке, частичные ответы (206) больше не сжимаются;
🔘
🔘 в 1.6.0 появился
Starlette лежит под FastAPI, так что изменение задевает и его. Полный список правок по версиям в release notes.
@zen_of_python
GZipMiddleware и подтянута защита FileResponse.GzipFile используется zlib.compressobj, и компрессор создаётся лениво;FileResponse отклоняет перевёрнутый однобайтовый Range и ограничивает число диапазонов сотней;max_body_size и поддержка расширения http.response.debug.Starlette лежит под FastAPI, так что изменение задевает и его. Полный список правок по версиям в release notes.
@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
pip 26.2 стал учитывать
🔘
🔘 экспериментальный режим
🔘 добавлены поддержка Python 3.15, self-referential extras, флаг
🔘 закрыты утечка системных пакетов в изолированную сборку на 3.15, несовпадение метаданных PEP 658, symlink traversal в tar-архивах и CVE-2026-13346;
🔘 26.2.1 вернул использование keyring из неактивированного virtualenv.
@zen_of_python
Cache-Control индекса, и это первое, что заметят пользователи: только что опубликованный пакет может не появиться сразу, если между вами и PyPI кэширующий прокси. Для принудительного обновления есть --refresh-package. Релиз вышел 29 июля, 26.2.1 — 4 августа.PIP_CONSTRAINT больше не влияет на изолированные сборочные окружения; для них появились --build-constraint и PIP_BUILD_CONSTRAINT;venv-isolation запускает сборку в обычных virtualenv вместо временных окружений;--only-deps и поле upload-time в pylock.toml;@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
CPython официально поддерживает RISC-V. Стан Ульбрих объявил об этом 24 августа в Python Insider: архитектура добавлена в PEP 11 как платформа третьего уровня.
RISC-V — открытая архитектура набора команд: в отличие от x86 и ARM, её может реализовать кто угодно. В записи ссылаются на прогноз, по которому экосистема вырастет вчетверо к 2032 году.
Держится всё на живом железе: несколько машин RISC-V передал проект RISE, на них крутятся боты сборки. Автор благодарит Людовика Анри из RISE, Фуркана Ондера и Эмму Смит, а свою работу вёл при поддержке Sovereign Tech Agency.
Что дальше. Боты сборки запускаются уже после слияния патча, поэтому команда разбирается, как завести RISC-V прямо в CI CPython — через инициативу RISE RISC-V Runners. В долгую цель — второй уровень поддержки и оптимизации под саму архитектуру.
Отдельно просят тех, у кого есть железо: собрать CPython, прогнать свои задачи и тесты и рассказать, что сломалось.
@zen_of_python
RISC-V — открытая архитектура набора команд: в отличие от x86 и ARM, её может реализовать кто угодно. В записи ссылаются на прогноз, по которому экосистема вырастет вчетверо к 2032 году.
Держится всё на живом железе: несколько машин RISC-V передал проект RISE, на них крутятся боты сборки. Автор благодарит Людовика Анри из RISE, Фуркана Ондера и Эмму Смит, а свою работу вёл при поддержке Sovereign Tech Agency.
Что дальше. Боты сборки запускаются уже после слияния патча, поэтому команда разбирается, как завести RISC-V прямо в CI CPython — через инициативу RISE RISC-V Runners. В долгую цель — второй уровень поддержки и оптимизации под саму архитектуру.
Отдельно просят тех, у кого есть железо: собрать CPython, прогнать свои задачи и тесты и рассказать, что сломалось.
@zen_of_python
👍2
Михаил Суриков собрал конвейер, который берёт сгенерированный моделью код на Python, ищет в нём уязвимости, чинит и проверяет заново. Сканируют параллельно CodeQL и Bandit, отдельная модель-валидатор смотрит своим взглядом, находки обогащаются техниками MITRE ATT&CK и примерами CWE, после чего другая модель пишет исправление.
Проверяли на 26 промптах из LLMSecEval, девяти категориях CWE и четырёх моделях Claude — всего 80 прогонов. Если валидатору дополнительно показать находки CodeQL и Bandit, число срабатываний статических анализаторов падает на 29–69% против 9–54% без этого.
Интересного тут два. Во-первых, само исправление в 15–22% случаев заносит новую уязвимость, и примерно в 70% таких случаев это ровно одна новая находка. Во-вторых, лучшая модель-генератор не дала лучший результат в конвейере: меньше всего остаточных находок и выше процент успешных починок оказались у Sonnet 4.6, а не у Opus 4.8.
@zen_of_python
Проверяли на 26 промптах из LLMSecEval, девяти категориях CWE и четырёх моделях Claude — всего 80 прогонов. Если валидатору дополнительно показать находки CodeQL и Bandit, число срабатываний статических анализаторов падает на 29–69% против 9–54% без этого.
Интересного тут два. Во-первых, само исправление в 15–22% случаев заносит новую уязвимость, и примерно в 70% таких случаев это ровно одна новая находка. Во-вторых, лучшая модель-генератор не дала лучший результат в конвейере: меньше всего остаточных находок и выше процент успешных починок оказались у Sonnet 4.6, а не у Opus 4.8.
@zen_of_python
Встречайте новую мини-игру — «Отпуск».
За несколько шагов нужно подготовить героя к поездке: навести порядок, разобрать вещи, отыскать билет и упаковать чемодан. Отдельный этап — отпускной гардероб, и тут всё непросто.
Простое управление, короткие уровни, юмор. Отличный способ отвлечься на пару минут между задачами и заодно поймать промокоды от партнёров!
Попробовать: https://tprg.ru/H2cI
За несколько шагов нужно подготовить героя к поездке: навести порядок, разобрать вещи, отыскать билет и упаковать чемодан. Отдельный этап — отпускной гардероб, и тут всё непросто.
Простое управление, короткие уровни, юмор. Отличный способ отвлечься на пару минут между задачами и заодно поймать промокоды от партнёров!
Попробовать: https://tprg.ru/H2cI