Быстрая замена mypy на Rust'е: pyrefly
Еще одно видео про еще один новый тайпчекер для питона на расте!
Много их нынче стало.
В видео:
- Обсуждаем первую версию: pyre-check, обсудили taint analysis
- Сравниваем pyrefly с ty и mypy
- Смотрим на внутреннее устройство
- Применяем на реальном проекте
Ключевые ссылки из выпуска:
– Доклад о pyrefly на PyCon: https://youtu.be/ZTSZ1OCUaeQ?si=s_DPOOzsdeTk5Uqo
– pyrefly vs ty: https://blog.edward-li.com/tech/comparing-pyrefly-vs-ty (сильно советую!)
Вывод: пока очень сырой, много багов, но быстрый. Ключевой вывод: отлично, что есть конкуренция.
Про Rust
Читщит По Умным Указателям
В Rust необычная схема управления памятью. Он не использует сборщик мусора, как в Java и Go, что делает его быстрым. Скорость Rust сопоставима со скоростью C.
Однако и у этой схемы есть минусы. Для того чтобы их решить, были введены умные указатели, которые дают возможность оперировать памятью на низком уровне с тем же удобством.
В статье специально использованы простейшие примеры, чтобы понять их было легче.
Типы
Box
Нужен для хранения объектов в куче, а не на стеке.
Обычно используется для рекурсивных типов, где размер объекта неизвестен во время компиляции.
Пример кода, который не будет работать.
struct Expression {
operator: Operator,
left: Expression, // Ошибка: recursive type has infinite size
right: Expression, // Ошибка: recursive type has infinite size
}
Чинится обертыванием left и right в Box.
struct Expression {
operator: Operator,
left: Box<Expression>,
right: Box<Expression>,
}
Rc
Позволяет нескольким переменным владеть одним объектом размещенным в куче.
Не работающий код.
let a = "Hello, World!".to_string();
let b = a;
let c = a; // Ошибка: use of moved value
Чтобы он заработал, добавим Rc.
let a = Rc::new("Hello, World!".to_string());
let b = Rc::clone(&a);
let c = Rc::clone(&a);
Код также будет работать если мы скопируем объект.
let a = "Hello, World!".to_string();
let b = a.clone();
let c = a;
Но прямое копирование может серьезно повредить производительности. Преимущество Rc в том, что при присваивании не создаётся новый объект, а даётся ссылка на уже существующий.
Arc
То же что и Rc, но безопасное для использования в многопоточных приложениях. Это значит, что его можно использовать из разных потоков, не боясь гонок данных.
let a = Arc::new(1);
let b = Arc::clone(&a);
let c = Arc::clone(&a);
Дороже с точки зрения производительности из-за способа подсчёта ссылок.
RefCell
Позволяет изменять данные внутри себя даже если объявлен как неизменяемый.
let a = RefCell::new(1);
*a.borrow_mut() += 1;
dbg!(a); // 2
Комбо
RefCell часто комбинируют с Rc в виде Rc<RefCell<T>>. Это позволяет каждому владельцу ссылки изменять общий объект.
let a = Rc::new(RefCell::new(1));
let b = Rc::clone(&a);
let c = Rc::clone(&a);
*b.borrow_mut() += 1;
dbg!(&a); // 2
dbg!(&c); // Тоже 2
*c.borrow_mut() += 1;
dbg!(&a); // 3
dbg!(&b); // Тоже 3
Заключение
Главное преимущество умных указателей – избегание ошибок типа segfault и выстрелов в ногу, характерных для C и C++, сохраняя при этом удобство использования.
Если статья была полезной, вас могут заинтересовать и другие статьи в моём телеграм-канале.
Хороший пре-коммит хук для Python разработчиков
Что такое pre-commit hook? Возможность автоматически проверять код перед коммитом. Может быть разное: прогонять тесты, линтеры, форматтеры...
И я собрал для вас быстрый набор из прекоммит хуков, которые вы можете использовать на любых проектах.
Что в него входит:
- ruff (быстрейший форматтер, делает код красивым)
- pyright (один из быстрейших статических анализаторов кода на Python, посвечивает ошибки в тайп-хинтах. что-то типа проверки типов при компиляции)
- pytest с расширением doctest (прогоняет имеющиеся юнит тесты вместе с тестами в документации, про которые я писал ранее. я еле как нашёл пре коммит хук для этого...)
Как установить?
1. сначала
pip install pre-commit
2. потом создаётё .pre-commit-config.yaml
3. потом вставляете туда
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.5
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix, --show-fixes ]
- id: ruff-format
- repo: local
hooks:
- id: pytest
args: [ --doctest-modules ]
name: pytest
entry: pytest .
language: system
types: [python]
pass_filenames: false
always_run: true
- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.385
hooks:
- id: pyright
4. пишете
pre-commit install
Энджой :)
Ссылка на оригинальный пост:
https://t.me/sh1nke9/375