partial или lambda: как специализировать колбэк без сюрпризов
Разница с
Сравнение двух способов специализации функций сводится к питоничному правилу: если нужно только связать аргументы, подходит
functools.partial заранее связывает часть аргументов и возвращает вызываемый объект. Сохранённые именованные аргументы работают как значения по умолчанию: при вызове их можно переопределить. Проверки новой сигнатуры при этом нет, поэтому повторная передача одного параметра закончится TypeError.Разница с
lambda проявляется во времени связывания. Лямбда получает текущее значение имени при выполнении, а partial сохраняет переданный объект при создании. Но копии не делает: изменения связанного списка будут видны, а долгоживущий колбэк удержит контекст в памяти.Сравнение двух способов специализации функций сводится к питоничному правилу: если нужно только связать аргументы, подходит
partial. Если адаптер проверяет данные, логирует или преобразует аргументы, яснее написать именованную функцию через def.Nalar
Practical Function Specialization in Python with functools.partial
Use Python functools.partial to build focused callables for callbacks and configuration while keeping argument binding explicit and predictable.
🫡2
Как OpenBLAS ускоряет NumPy в браузере
Раньше браузерная сборка NumPy выполняла
Прирост зависит от операции. Функции
Бенчмарки и настройки стенда помогают сравнивать сборки по размеру матриц, типу данных и браузеру, а не переносить одну красивую цифру на весь NumPy.
Раньше браузерная сборка NumPy выполняла
np.matmul обычными циклами на C, которые не учитывали кэш процессора и векторные инструкции. Теперь NumPy 2.5.3 из Emscripten-forge по умолчанию подключает OpenBLAS 0.3.34 для WebAssembly. На квадратных матрицах 1024 × 1024 умножение ускорилось примерно в 30,92 раза для float32 и в 14,90 раза для float64.Прирост зависит от операции. Функции
np.linalg ускорились слабее, поскольку реализация LAPACK ещё не оптимизирована специально для WebAssembly. Экспериментальная OpenBLAS 0.3.35 добавляет новые векторные ядра, а сборка с Relaxed SIMD даёт дополнительное ускорение только в браузерах с поддержкой этого расширения.Бенчмарки и настройки стенда помогают сравнивать сборки по размеру матриц, типу данных и браузеру, а не переносить одну красивую цифру на весь NumPy.
🙏1🍾1
Как проверять плагины через контракт Pydantic и FastAPI
Сервис может отвечать по нужным адресам и всё же возвращать несовместимые данные. В схеме общего API-контракта модели Pydantic для
Плагин использует эти модели в обработчиках FastAPI, а платформа проверяет ими ответы при регистрации. Если структура не совпадает, сервис не подключается.
Контракт фиксирует и ответственность: разбиением входных данных управляет плагин, а проверки доступа вынесены в зависимости FastAPI. Это ловит несовместимый формат до подключения, но не проверяет правильность вычислений.
Сервис может отвечать по нужным адресам и всё же возвращать несовместимые данные. В схеме общего API-контракта модели Pydantic для
/ready, /catalog и /encode/ вынесены в отдельный пакет.Плагин использует эти модели в обработчиках FastAPI, а платформа проверяет ими ответы при регистрации. Если структура не совпадает, сервис не подключается.
Контракт фиксирует и ответственность: разбиением входных данных управляет плагин, а проверки доступа вынесены в зависимости FastAPI. Это ловит несовместимый формат до подключения, но не проверяет правильность вычислений.
😨2🤯1😘1
Как битовые множества сокращают память моделей Pydantic
Explicit is better than implicit, но хранить набор явно переданных полей в полноценном Python
Поскольку поля модели упорядочены, каждому можно назначить номер бита: 1 означает, что значение передали при создании, 0 — что использовано значение по умолчанию. Имена дополнительных полей, которых нет в схеме, остаются в отдельном
В разборе реализации показано, как выбирать
Explicit is better than implicit, но хранить набор явно переданных полей в полноценном Python
set оказалось накладно. Memray показал: создание model_fields_set заняло почти 800 МБ на миллионе экземпляров модели с семью полями.Поскольку поля модели упорядочены, каждому можно назначить номер бита: 1 означает, что значение передали при создании, 0 — что использовано значение по умолчанию. Имена дополнительных полей, которых нет в схеме, остаются в отдельном
set.В разборе реализации показано, как выбирать
u8, u16 или вектор для моделей разного размера. На тесте с небольшими значениями замена сократила память на 55%. Полезный пример того, почему профилировать стоит не только __dict__, но и служебные структуры каждого экземпляра.❤1☃1
Как отменять задачи в heapq и сохранять порядок при равных приоритетах
Искать и удалять произвольную запись по идентификатору куча эффективно не умеет. Для отмены и смены приоритета можно хранить активные записи в словаре: старую помечать удалённой, новую добавлять в кучу, а помеченные пропускать при извлечении. Лень здесь вполне питонична.
У этой схемы очереди есть цена: устаревшие записи занимают память, пока не доберутся до вершины. Если обновлений много, а извлечений мало, кучу стоит периодически пересобирать из активных записей.
heapq сравнивает кортежи по полям. Поэтому запись (приоритет, задача) при равных приоритетах либо сравнит сами задачи, либо упадёт, если объекты несравнимы. Надёжная форма: (приоритет, номер, задача), где номер выдаёт itertools.count(). Он сохраняет порядок добавления и не допускает сравнения задач.Искать и удалять произвольную запись по идентификатору куча эффективно не умеет. Для отмены и смены приоритета можно хранить активные записи в словаре: старую помечать удалённой, новую добавлять в кучу, а помеченные пропускать при извлечении. Лень здесь вполне питонична.
У этой схемы очереди есть цена: устаревшие записи занимают память, пока не доберутся до вершины. Если обновлений много, а извлечений мало, кучу стоит периодически пересобирать из активных записей.
❤1👀1
Как воспроизводить гонки потоков Python с помощью blanket
Обычно порядок выполнения потоков выбирает ОС, поэтому редкая гонка превращает тест в лотерею. blanket оборачивает примитивы
В
Это полезно при переносе библиотек на Python без GIL, но управление порядком потоков работает на границах примитивов синхронизации. Для гонки внутри голого
Обычно порядок выполнения потоков выбирает ОС, поэтому редкая гонка превращает тест в лотерею. blanket оборачивает примитивы
threading, а тест сам решает, какой поток продолжит работу. Пять повторов перестают быть стратегией тестирования.В
Scenario можно заставить поток B захватить блокировку раньше A, задать порядок освобождения барьера или выбрать поток, который разбудит notify(). Каждый такой вызов приостанавливается в планировщике blanket, поэтому сценарий повторяется одинаково.Это полезно при переносе библиотек на Python без GIL, но управление порядком потоков работает на границах примитивов синхронизации. Для гонки внутри голого
counter += 1 нужна дополнительная контрольная точка. blanket закрепляет известный порядок в регрессионном тесте, а не перебирает все возможные гонки.🔥2🥰1
Пакетная обработка в Python: где strict=True не спасает запись
С Python 3.12
С Python 3.13 параметр
Явное лучше неявного: для записи по принципу «всё или ничего» заранее проверьте конечный источник либо используйте транзакцию системы назначения. Разбор itertools.batched() также объясняет, почему
С Python 3.12
itertools.batched() лениво забирает из итератора элементы только для очередного кортежа. Поток из файла, курсора или генератора не приходится сначала превращать в список: памяти для группировки нужно столько, сколько занимает один пакет, а не весь источник.С Python 3.13 параметр
strict=True отклоняет неполный последний пакет. Но ошибка возникает во время итерации. При 250 записях и размере пакета 100 первые 200 уже могут попасть в базу, прежде чем оставшиеся 50 вызовут ValueError. Строгость проверяет форму входа, а не делает цикл транзакцией.Явное лучше неявного: для записи по принципу «всё или ничего» заранее проверьте конечный источник либо используйте транзакцию системы назначения. Разбор itertools.batched() также объясняет, почему
list(batched(...)) лишает обработку преимущества ленивости.Nalar
Batch Python Iterables Lazily with itertools.batched
Learn how itertools.batched groups Python iterables lazily, how partial final batches behave, when strict mode helps, and where batching does not provide concurrency or transaction guarantees.
❤1
Как выстроить защиту цепочки поставок Python
Эшелонированная схема защиты начинается с собственного кода: Ruff находит секреты, слабую криптографию и запросы без тайм-аута до публикации пакета.
Зависимости и их криптографические хеши фиксируют через
Хеши не распознают изначально вредоносный пакет, а аудит пропускает неизвестные уязвимости. Поэтому начать стоит с Ruff и фиксации зависимостей, затем добавить аудит и SBOM.
Эшелонированная схема защиты начинается с собственного кода: Ruff находит секреты, слабую криптографию и запросы без тайм-аута до публикации пакета.
Зависимости и их криптографические хеши фиксируют через
uv lock или uv pip compile --generate-hashes. Затем pip-audit ищет в CI известные уязвимости, а SBOM помогает понять, затронул ли проект компрометированный пакет. Trusted Publishing с OIDC заменяет долгоживущие API-токены.Хеши не распознают изначально вредоносный пакет, а аудит пропускает неизвестные уязвимости. Поэтому начать стоит с Ruff и фиксации зависимостей, затем добавить аудит и SBOM.
Как не сломать pickle собственным исключением Python
Если конструктор исключения принимает
Питоничный инвариант прост:
Пример с ValidationError показывает поломку и совместимый вариант класса.
Если конструктор исключения принимает
field и reason, не заменяйте их готовой строкой при вызове super().__init__(). Иначе в args останется один элемент, а при восстановлении BaseException.__reduce__ передаст его обратно конструктору. Тот ждёт два аргумента, поэтому распаковка завершится TypeError. Так же ломаются copy.copy() и передача исключения между процессами.Питоничный инвариант прост:
args должны оставаться корректным списком аргументов для вашего __init__. Передавайте в базовый класс исходные field и reason, храните структурированные данные в атрибутах, а читаемое сообщение формируйте в __str__.Пример с ValidationError показывает поломку и совместимый вариант класса.
Seroze’s blog
[Python] Exception Handling: The Parts I Got Wrong
Notes from working through an exception-handling quiz. Everything below was verified on CPython 3.12 rather than recalled — the sections marked trap are the ones I actually got wrong, and they cluster around one theme: the hierarchy and the unwind, not the…
🤪1
Охрана трубопровода длиной 400 километров
Камеры на столбах не заглянут за угол, дрон висит 30-40 минут и летит заряжаться, а охранник-человек — дорого, медленно и небезопасно на протяжённом объекте.
Технический разбор робопса изнутри: что скрыто под закрытым ядром биомеханики, какой стек сенсоров закрывает слепые пятна друг друга — лидар боится стекла, поэтому рядом ставят сонар.
Как рой из нескольких собак строит p2p-сеть, чтобы одна работала мостом для другой за горизонтом связи в техническом разборе робопса.
Камеры на столбах не заглянут за угол, дрон висит 30-40 минут и летит заряжаться, а охранник-человек — дорого, медленно и небезопасно на протяжённом объекте.
Технический разбор робопса изнутри: что скрыто под закрытым ядром биомеханики, какой стек сенсоров закрывает слепые пятна друг друга — лидар боится стекла, поэтому рядом ставят сонар.
Как рой из нескольких собак строит p2p-сеть, чтобы одна работала мостом для другой за горизонтом связи в техническом разборе робопса.
❤🔥1👍1
Как вернуть значение из всплывающего окна в форму Django Admin
Django Admin умеет создавать связанный объект во всплывающем окне и сразу подставлять его в исходную форму. Практический разбор этого механизма показывает, как переиспользовать его для собственного инструмента выбора значений.
Пример связывает
Питоничность здесь в композиции готовых частей: представление может вычислить значение любым способом, а JavaScript админки доставит результат в нужное поле. Цена переиспользования — зависимость от соглашений Django Admin: специального идентификатора ссылки и функций из
Django Admin умеет создавать связанный объект во всплывающем окне и сразу подставлять его в исходную форму. Практический разбор этого механизма показывает, как переиспользовать его для собственного инструмента выбора значений.
Пример связывает
ModelAdmin, отдельное представление, URL и шаблон. Ссылка вызывает showRelatedObjectLookupPopup, а кнопка во всплывающем окне через opener.dismissRelatedLookupPopup возвращает выбранную строку в поле формы и закрывает окно.Питоничность здесь в композиции готовых частей: представление может вычислить значение любым способом, а JavaScript админки доставит результат в нужное поле. Цена переиспользования — зависимость от соглашений Django Admin: специального идентификатора ссылки и функций из
RelatedObjectLookup.js.