Rust для Python-разработчиков
easy

Rust для Python-разработчиков

Чем они похожи и нужно ли учить второй язык

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

Rust — молодой язык программирования, который сложнее в изучении, зато код на нём работает быстрее. Если нужно ускорить программу, написанную на Python, можно написать часть кода на Rust и запускать эту часть из Python-скрипта.

Сегодня разберём, для каких задач ещё подходит Rust, установим его на компьютер и посмотрим, как он вообще выглядит для человека, знакомого с Python.

Что такое Rust

Rust начал разрабатывать один из разработчиков Mozilla Грэйдон Хорр в 2006 году как личный проект, а в 2009 Mozilla начала официально спонсировать проект. Первая готовая для массового использования версия появилась в 2015 году.

Вместо кардинально новых функций Хорр сосредоточился на безопасности языка: собирал уже работающие методы и возможности и делал их работу надёжнее и быстрее. Это отражено в названии языка, который назван в честь ржавчинных грибов (rust по-английски — «ржавый»), которые очень живучие и быстро растут.

Сейчас это производительный, обеспечивающий безопасность памяти язык, которой защищает код от целого ряда ошибок, которые может совершить программист. У Rust понятный синтаксис в котором легко разобраться, встроенный менеджер пакетов, и код на нём легко поддерживать и исправлять благодаря понятным сообщениям об ошибках.

Получается, что Rust не делает ничего нового, зато в нём нет недостатков других языков:

  • он быстрее простых универсальных языков вроде Python или Ruby, хотя сложнее;
  • Rust, как и Python, защищает код от ошибок — но при этом не ограничивает возможности программы;
  • Rust безопаснее C или C++, при этом часто почти такой же по скорости.

Кто использует Rust

Rust — мощный и безопасный язык, который может стать хорошей заменой C++. Конечно, переписывать огромные базы кода на другом языке долго и дорого, но многие компании делают это постепенно: например, основная часть Windows написана на C, но разработчики уже переписывают самые уязвимые части кода на Rust.

Вот отрасли и компании, которые используют Rust или внедрили его для некоторых фрагментов:

  • Облачная инфраструктура и бэкенд-технологии (AWS, Google).
  • Web3 — идея интернета на основе блокчейна (Near, Ethereum).
  • Операционные системы (Linux, Windows, Android).
  • Браузеры (Mozilla Firefox).
  • Базы данных (Surreal DB).
  • Интернет вещей (Samsung).
  • Кибербезопасность (Microsoft, 1Password).
  • Финансы (Two Sigma, Kraken).
  • Машинное обучение и Data Science (Grok, polars).
  • Авиационное и космическое производство (NASA, Cryptosat и Airhart).
  • Роботостроение (Scythe Robotis, Tangram Visions).
  • Разработка игр (Embark Studios и Ready at Dawn).

Запуск кода на Python

Отличие Rust от Python в том, что Python интерпретируемый язык, а Rust — компилируемый. Сейчас поясним, что это значит.

На Python, достаточно написать код и его сразу можно запускать. Например:

print('Привет, Python-код!')

Для запуска можно нажать специальную кнопку в среде разработки IDE или ввести такую команду в терминале, находясь в папке проекта, — просто пишем название файла со скриптом:

python hello_world.py

В консоли получим:

Установка и запуск кода на Rust

Rust — это компилируемый язык: написанный код компьютеру нужно сначала проверить, а потом перевести это на язык машинных команд. Для запуска кода нужно сначала установить Rust, например такой командой в терминале:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Проверить установку можно так:

rustc --version

Если всё в порядке, в консоли мы увидим номер установленной версии компилятора Rust. После этого можно написать первый код и сохранить его как hello_world.rs:

fn main() {
   println!("Привет, первый Rust-код!");
}

👉 Это выглядит немного сложнее, чем то же самое Python, но если вы знаете хотя бы основы Python, то легко сможете понять, что тут происходит.

Запустить Rust-код одной командой или кнопкой нельзя, сначала его нужно скомпилировать. Самый простой способ сделать это на Rust — воспользоваться встроенным менеджером пакетов Cargo, который применяется в большинстве задач на этом языке.

Допустим, если мы хотим выполнить код выше, нужно сначала создать проект. Чтобы не создавать все нужные для этого файлы вручную, открываем терминал, переходим в каталог с нашим скриптом и пишем такое:

cargo new hello_world

В том каталоге, где выполнена команда, появится папка hello_world. В ней будет отдельная папка с нашим скриптом на Rust и файл-манифест с инструкциями Cargo.toml на языке TOML, который необходим для компиляции.

Чтобы скомпилировать код, нужно перейти в папку hello_world и в терминале выполнить команду:

cargo build

Внутри проекта появится ещё одна папка — target\debug, в который будет лежать исполняемый файл hello_world. На Windows-системах у него будет расширение .exe, а на MacOS или Linux у таких файлов вообще нет расширения — просто hello_world.

Чтобы запустить код, нужна такая команда:

cargo run

В консоли мы увидим, что файл сначала компилируется, потом запускается. После этого получаем результат работы написанного кода:

❗️ Запускать код на Rust дольше, чем на Python, но неудобно только при первом знакомстве. Зато код защищён от большого количества ошибок и работает быстрее.

Типизация данных в Python

Чтобы лучше понять типизацию в Rust, сначала посмотрим, как это сделано в Python.

Python — динамически типизируемый язык. Любой переменной можно присваивать любое значение: строку, целое число или число с плавающей запятой, список, словарь, кортеж. После присваивания мы можем заново установить значение: сначала в переменной была строка, в середине программы мы положили туда число, а к концу выполнения — словарь.

Переприсваивание может привести к беспорядку, поэтому хорошим тоном при разработке на Python являются подсказки к переменным, которые называются аннотациями типов. После каждой переменной в программе разработчик подписывает, что за тип данных может в ней находиться, и этот тип данных не меняется.

Аннотации типов выглядят так:

# тип данных для переменной x - целое число
# присваиваем переменной значение 1000
x: int = 1000

# тип данных для переменной y - строка
# присваиваем переменной значение 'Привет, КОД'
y: str = 'Привет, КОД!'

# тип данных для переменной z - словарь
# объявляем переменную и пока не присваиваем ей значение
z: dict

Аннотации типов ни к чему не обязывают. Даже с ними можно хранить в переменных любые данные и менять их за программу любое количество раз, это не будет ошибкой.

Типизация данных в Rust

Rust — статически типизируемый язык. Это значит, что память на все переменные выделяется на этапе компиляции, поэтому программа должна понимать, что хранится в каждой переменной.

В некоторых статически типизируемых языках, таких как C, C++ или Java, для этого нужно указывать обязательные аннотации типов к каждой переменной. В Rust так тоже можно. Типы данных указываются так же, как в Python — через двоеточие:

// тип переменной - строка
let alphabet: char = 'A';

// тип переменной - целое число, которое занимает в памяти 32 бита
let number: i32 = 200;

// переменная булевого типа со значением true
let flag1: bool = true;

Но такие аннотации в Rust указывать необязательно, потому что он сам понимает, что за тип данных соответствует присвоенному значению. 

Например, в этой переменной Rust сам увидит целое 8-битное число типа u8 и запросит нужное количество оперативной памяти:

let elem = 5u8;

Ещё переменные в Rust можно изменять, если присвоить им тип mut. Такой код выполнится без ошибок:

// Изменяем переменную типа mut
let mut a = 5;
a = 6;

Python-разработчикам такой подход покажется удобным и знакомым: аннотации писать необязательно, а переменные можно переприсваивать — правда, только в пределах своего типа. Нельзя объявить переменную let mut a = 5 и потом записать в неё строку.

В итоге код получается аккуратнее и заставляет продумывать ход программы, чтобы использовать типы данных с минимальной загрузкой оперативной памяти.

Классы Python и структуры Rust

Python

В программировании есть две основных парадигмы: объектно-ориентированное программирование (ООП) и функциональное программирование.

Python работает по принципам объектно-ориентированного программирования. Мы можем создать класс — шаблон кода — и задать для него несколько способов, которыми этот класс можно использовать. Эти способы называются методы.

Например, можно создать класс User и описать для него методы работы с именем и адресом электронной почты:

# объявляем класс
class User:
   # настраиваем метод при создании объекта класса
   def __init__(self, name):
       # при создании нужно будет задать имя
       self.name = name
       # почта создастся автоматически с использованием имени и шаблона
       self.email = name + '@mail.code.ru'

   # настраиваем второй метод, при вызове нужно
   # задать сообщение для аргумента message
   def send_email(self, message):
       # при вызове метод выводит строку с сообщением
       print(f'На {self.email} отправлено {message}')

Ещё мы можем на основе первого класса создать другой класс — тогда во втором классе будут доступны те же методы.

Rust

Rust — полностью функциональный язык, классов и наследования в нём нет.

Сложные типы данных создаются через структуры — группы данных, которые потом можно использовать по отдельности. Это может выглядеть так:

// создаём структуру User c двумя методами-полями:
struct User {
   name: String,
   email: String
}

Чтобы пользоваться методами, их нужно создать отдельно. Это делается через ключевое слово impl и указание названия структуры:

// реализуем методы для структуры
impl User {
   // метод new создаёт новый экземпляр User
   // он принимает ссылку на строку &str и возвращает объект типа User
   fn new(name: &str) -> User {
       // прописываем тело функции
       User {
           // конвертируем строку name из типа &str в String
           name: name.to_string(),
           // создаём строку с форматом email
           email: format!("{}@mail.code.ru", name)
       }
   }
}

Вместе готовыми методами можно писать основную функцию — при запуске скрипта запустится именно она:

// основная функция, которая запускается при старте программы
fn main() {
   // создаём переменную user и присваиваем ей объект структуры User
   let user = User::new("Игорь");
   // выводим на экран приветствие с именем пользователя
   println!("Привет, {}!", user.name);
   // выводим email пользователя
   println!("Ваша электронная почта: {}", user.email);
}

Как совместить плюсы обоих языков

Многие библиотеки Python написаны на других языках, а через Python их можно использовать с привычным удобным синтаксисом. Так работают библиотеки для обработки больших данных, например NumPy или SciPy.

На Rust библиотеки для Python тоже есть, например polars — ещё одно расширение для работы со сложными высоконагруженными операциями.

Можно написать своё расширение для Python на Rust со своими функциями — для этого есть специальная библиотека PyO3. Она позволяет совместить преимущества обоих языков. Это интересная, но сложная тема, и про работу с PyO3 подробно расскажем в отдельной статье. Если кратко:

  • Rust позволяет писать безопасный код, который может выполнять несколько операций одновременно;
  • поэтому сначала мы пишем модуль на Rust и создаём быстрые функции;
  • после этого из Python-кода можно вызвать этот модуль и пользоваться преимуществами Rust как обычной библиотекой.

Нужен ли Rust, если есть Python

Если программы на Python выполняют свои задачи, работают без частых поломок и не предназначены для высоких нагрузок и большого количества пользователей — не нужен.

С другой стороны, Rust активно развивается, его функции можно добавлять в Python, а ещё для Python-разработчика учить его будет уже не так сложно, как начинать с нуля. Поэтому, если Python вам мало — точно стоит попробовать Rust.

Обложка:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Мария Климентьева

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Еще по теме
easy
[anycomment]
Exit mobile version