Python. IT-курсы разрекламировали его как один из самых легких языков для входа в разработку, любители ИИ создают на нем свои первые нейросети, а некоторые сеньоры Java и C++ по-прежнему смотрят на него свысока, считая недостаточно строгим и производительным для «серьезной» разработки. В любом случае сегодня о Python знают все.
Поскольку заметный рост его популярности пришелся на 2010-е годы, многие считают, что язык появился сравнительно недавно. Но это неверно: Python старше большинства современных веб- и ML-фреймворков, массовой мобильной разработки и нынешнего AI-бума.
Как язык с репутацией медленного стал основным инструментом data science и машинного обучения, почему он поднялся на вершину рейтингов популярности и какую роль в этом сыграли его архитектура и экосистема — разберем в этой статье.
История Python: язык из 1989 года, который дождался своего времени
Поскольку Python стал хайповым относительно недавно, можно было бы предположить, что он был изобретен где-то в 2000-х. Но это далеко не так.
Python появился в конце 1980-х в Нидерландах. Его создатель — Гвидо ван Россум, программист из Центра математики и информатики (CWI) в Амстердаме. Он начал проектировать Python в декабре 1989 года. Первый рабочий вариант появился в 1990-м, а версия 0.9.0 была публично выпущена 20 февраля 1991 года. Название язык получил не в честь змеи, а в честь любимого британского комедийного шоу Гвидо Monty Python’s Flying Circus («Летающий цирк Монти Пайтона»).
Непосредственной причиной появления языка был проект Amoeba. Это экспериментальная микроядерная распределенная операционная система, разрабатывавшаяся CWI и Vrije Universiteit Amsterdam: она должна была представить сеть рабочих станций, файловых серверов и пула процессоров как единую вычислительную систему с прозрачным размещением программ и данных.
Для Amoeba требовались системные административные утилиты. Писать их на C было слишком трудоемко, а Bourne shell оказался недостаточно удобен для работы с механизмами новой распределенной операционной системы. По словам самого ван Россума, потребовался язык, который мог бы «закрыть разрыв между C и shell». На дизайн Python также существенно повлиял язык ABC, над которым ван Россум ранее работал в CWI.
Уже в исходной задаче просматривается будущая роль Python: язык предназначался для координации компонентов и быстрого описания логики, тогда как низкоуровневые функции могли оставаться в системном коде. Возможность расширять Python модулями на C и C++ впоследствии стала штатной частью платформы, а не сторонним обходным решением.
Когда Python начал расти
У Python не было одного переломного года. Он постепенно распространялся в автоматизации, веб-разработке, образовании и научных вычислениях, после чего в 2010-х его рост заметно ускорили data science и machine learning.
Анализ Stack Overflow за 2017 год показывал, что в странах с высоким уровнем дохода рост посещаемости тега Python ускорялся начиная с 2013 года. В июне 2017-го Python впервые стал там самым посещаемым тегом среди языков, а его посещаемость с 2012 года увеличилась примерно в 2,5 раза. За пределами этой группы стран выраженный рост, по данным той же работы, начался примерно в 2014 году. Но нужно учитывать, что это статистика просмотров Stack Overflow, а не прямое измерение объема промышленного кода.
В опросе Stack Overflow 2019 года Python обошел Java по доле респондентов, использовавших язык, и был снова назван самым быстрорастущим крупным языком. По состоянию на июль 2026 года Python занимает первое место в TIOBE с рейтингом 18,94%, опережая C, C++, Java и C#.
Таким образом, машинное обучение стало одним из основных драйверов роста Python, но не единственным. Существенную роль также сыграли автоматизация, образование, веб-разработка, научные вычисления и общее расширение open source-экосистемы.
Почему развитие нейросетей вывело Python в лидеры
В 1990-е и 2000-е годы процессорное время и оперативная память были более ограниченными ресурсами, поэтому разработчикам чаще приходилось заранее оптимизировать программы под конкретное оборудование. Сегодня вычислительные мощности проще масштабировать с помощью облачных сервисов и ускорителей, а для бизнеса приоритетной стала скорость разработки.
Для машинного обучения это особенно важно. Архитектуру модели редко пишут один раз и больше не меняют. Исследователи перебирают способы подготовки данных, слои нейросети, функции потерь и гиперпараметры. В такой работе язык должен позволять быстро собирать рабочий прототип из готовых компонентов, изменять его и сразу оценивать результат.
Эту роль взял на себя Python. Его часто называют glue language — языком-клеем, который связывает библиотеки и компоненты, реализованные на разных языках. При этом Python не анализирует сложность операции и не решает, нужно ли передавать ее в C++: этот переход заранее заложен в реализации соответствующей библиотечной функции.
На практике схема выглядит так:
-
CPython выполняет пользовательский код и доходит, например, до вызова
torch.matmul()или слояnn.Linear. -
Python-интерфейс передает вызов внутренней реализации библиотеки.
-
Библиотека выбирает подходящий вариант операции для CPU или GPU.
-
Вычисления выполняет скомпилированный код: C, C++, Fortran, CUDA либо специализированная математическая библиотека.
-
Python получает объект с результатом и продолжает выполнение программы.
В документации PyTorch прямо указано, что Python-интерфейс передает в C++ практически все вычислительно тяжелые операции, особенно численные. Поэтому основную часть времени программа может проводить не внутри интерпретатора Python, а в оптимизированных CPU- или GPU-ядрах.
Почему тогда не выполнять всю работу на самом Python? Проблема проявляется прежде всего в коде, который последовательно обрабатывает отдельные Python-объекты. CPython выполняет байткод, определяет типы во время работы программы и несет дополнительные расходы при каждой операции. Поэтому цикл на чистом Python обычно значительно медленнее аналогичного цикла, скомпилированного из C++.
В исследовании USENIX ATC 2022 на наборе тестов LangBench приложения под CPython выполнялись в среднем в 29,5 раза медленнее соответствующих C++-реализаций. Это не универсальный коэффициент для любого кода и не сравнение скорости обучения нейросетей: результат относится к конкретному набору из двенадцати тестов. Он показывает, насколько заметными могут быть накладные расходы CPython, когда основная работа действительно выполняется интерпретатором.
В ML-нагрузках ситуация часто иная. Один вызов Python может запускать перемножение матриц, состоящих из миллионов элементов. Накладные расходы возникают при вызове операции, а вся тяжелая математика выполняется внутри нативного ядра. В результате Python позволяет быстро описывать и проверять гипотезы, одновременно передавая вычислительно сложные задачи C++, CUDA и специализированным библиотекам. Именно сочетание высокой скорости разработки на Python с возможностью передавать ресурсоемкие операции оптимизированным библиотекам и GPU сделало его особенно удобным инструментом для нейросетей и помогло занять лидирующее положение в ML-экосистеме.
Экосистема и сетевой эффект
Когда есть удобный язык, под него пишут библиотеки. А когда библиотек много, его используют еще больше.
К середине 2010-х вокруг Python сформировалась полноценная среда для научных вычислений и анализа данных. NumPy отвечал за работу с многомерными массивами, SciPy — за численные методы, pandas — за табличные данные, scikit-learn — за классические алгоритмы машинного обучения, а Matplotlib — за визуализацию. Связка IPython и Jupyter позволяла запускать код по частям, добавлять формулы, графики и пояснения в одном документе. При этом Jupyter — не Python-библиотека, а платформа, поддерживающая разные языки, хотя именно Python стал одним из ее основных сценариев использования.
Поэтому, когда Google открыл исходный код TensorFlow в ноябре 2015 года, а Facebook AI Research представила PyTorch в январе 2017-го, новые фреймворки пришли уже в зрелую экосистему. Их пользователи могли работать с привычными инструментами подготовки данных, визуализации и анализа, а вычислительно сложные операции выполнялись внутри фреймворков с помощью C++, CUDA и специализированных библиотек.
Так возник сетевой эффект: чем больше специалистов выбирали Python, тем больше появлялось библиотек, документации, учебных материалов и готовых решений. А чем богаче становилась экосистема, тем меньше причин оставалось переходить на другой язык.
Почему Python оказался удобным интерфейсом для ML
Машинное обучение находится на пересечении программирования, математики, статистики и конкретной предметной области. Многие дата-сайентисты и ML-исследователи приходят из физики, биологии, экономики или прикладной математики. Их основная задача — сформулировать гипотезу, подготовить данные, изменить архитектуру модели и оценить результат, а не вручную управлять памятью или реализовывать матричные операции.
Python позволяет работать ближе к уровню математической модели. Операции над массивами и тензорами записываются компактно, а код обычно отражает последовательность вычислений: загрузить данные, выполнить преобразование, получить предсказание, рассчитать ошибку и запустить обратное распространение градиента. В типовых ML-задачах специалисту не приходится самостоятельно реализовывать перемножение матриц, многопоточность или низкоуровневую работу с GPU.
Для исследовательской работы также важен короткий цикл проверки гипотезы. В Python нет отдельного ручного этапа сборки приложения после каждого изменения: можно заменить слой модели, изменить функцию потерь, перезапустить отдельную ячейку в Jupyter и сразу проверить промежуточные значения. PyTorch был разработан именно с акцентом на удобную отладку, гибкое описание моделей и совместимость с существующими инструментами научных вычислений.
Гибкость Python и eager-режим PyTorch дают исследователю больше свободы: можно быстро менять структуру модели, использовать обычные условия и циклы, выводить формы тензоров и проверять отдельные части вычислений. Отдельно работает autograd: во время прямого прохода он формирует граф вычислений для поддерживаемых операций, а вызов backward() автоматически рассчитывает градиенты, поэтому производные для каждого слоя обычно не приходится реализовывать вручную.
В итоге, к моменту распространения deep learning вокруг Python уже существовала развитая среда для работы с массивами, научными алгоритмами, табличными данными, визуализацией и интерактивными ноутбуками. Новым ML-фреймворкам не требовалось создавать весь инструментарий с нуля: они могли встроиться в уже привычный для исследователей рабочий процесс.
Это не означает, что C++ не используется дата-сайентистами и ML-инженерами. На нем пишут внутренние компоненты фреймворков, собственные операторы, высокопроизводительные пайплайны и системы с жесткими требованиями к задержкам. У PyTorch существует полноценный C++-интерфейс для обучения и запуска моделей без Python. Однако сами разработчики PyTorch рассматривают его как дополнение к Python-интерфейсу для случаев, когда этого требуют производительность, многопоточность или условия развертывания.
Python стал стандартным интерфейсом для ML не потому, что лучше C++ выполняет математические операции. Его преимущество заключается в другом: исследователь может описывать вычисления на высоком уровне, быстро менять эксперимент и пользоваться общей экосистемой, а реализацию тяжелых операций оставлять более производительным языкам и специализированному оборудованию.
Как это работает в коде
Код ниже показывает, как Python запускает обучение нейросети, а тяжелые вычисления передает внутренним компонентам PyTorch, написанным на C++ и CUDA. Профилировщик помогает увидеть, какие операции выполняются за обычными вызовами Python.
import torchimport torch.nn.functional as Ffrom torch import nnfrom torch.profiler import ProfilerActivity, profile, record_functiontorch.manual_seed(42)device = torch.device("cuda" if torch.cuda.is_available() else "cpu")batch_size = 512input_dim = 1024hidden_dim = 2048num_classes = 100# Синтетический batch: его размера достаточно,# чтобы матричные операции были заметны в профиле.features = torch.randn(batch_size, input_dim, device=device)labels = torch.randint( low=0, high=num_classes, size=(batch_size,), device=device,)classifier = nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.GELU(), nn.Linear(hidden_dim, num_classes),).to(device)classifier.train()optimizer = torch.optim.SGD( classifier.parameters(), lr=1e-2,)def train_step() -> torch.Tensor: """Один шаг обучения: forward, backward и обновление весов.""" optimizer.zero_grad(set_to_none=True) # Python вызывает слои модели, а операции над тензорами # передаются внутренним операторам PyTorch. logits = classifier(features) loss = F.cross_entropy(logits, labels) # Autograd запускает обратный проход и рассчитывает градиенты. loss.backward() optimizer.step() return loss.detach()# Прогрев исключает часть разовых расходов# на первоначальную инициализацию.for _ in range(3): train_step()if device.type == "cuda": torch.cuda.synchronize()activities = [ProfilerActivity.CPU]if device.type == "cuda": activities.append(ProfilerActivity.CUDA)with profile(activities=activities) as profiler: with record_function("training_step"): loss = train_step() # CUDA-операции выполняются асинхронно. # Перед формированием таблицы дожидаемся их завершения. if device.type == "cuda": torch.cuda.synchronize()sort_key = ( "device_time_total" if device.type == "cuda" else "cpu_time_total")print(f"device={device}, loss={loss.item():.4f}")print( profiler.key_averages().table( sort_by=sort_key, row_limit=15, ))
В конце программа выводит таблицу профилировщика. В ней обычно видны операции aten::linear, aten::addmm и aten::mm, которые отвечают за работу слоев и матричные вычисления. Python задает порядок действий, а сами расчеты выполняются оптимизированным кодом на процессоре или видеокарте.
Это не полноценный тест производительности: код профилирует только один шаг обучения, а сам профилировщик немного замедляет выполнение. Вызов torch.cuda.synchronize() нужен, чтобы перед выводом таблицы дождаться завершения всех операций на видеокарте.
Заключение
Python может уступать компилируемым языкам в скорости выполнения чистого CPU-кода, но для нейросетей это оказалось не главным. Он позволяет быстро описывать модели и проверять гипотезы, а ресурсоемкие операции передает оптимизированным библиотекам и GPU-ядрам. В сочетании с развитой научной экосистемой именно это сделало Python основным интерфейсом современной ML-разработки.
ссылка на оригинал статьи https://habr.com/ru/articles/1061952/