Антонио Куни — инженер, давно занимающийся повышением производительности Python, а также разработчик PyPy. Он провёл на EuroPython 2025 в Праге презентацию «Мифы и легенды о производительности Python». Как можно догадаться из названия, он считает многие общепринятые сведения о производительности Python как минимум вводящими в заблуждение. На множестве примеров он показал, где, по его мнению, таятся истинные проблемы. Инженер пришёл к выводу, что управление памятью в конечном итоге наложит ограничения на возможности повышения производительности Python, но у него есть проект SPy, который, возможно, станет способом реализации сверхбыстрого Python.

Он начал своё выступление с просьбы: «Если вы считаете Python медленным или недостаточно быстрым, поднимите руку»; поднялось много рук, в отличие от презентации на PyCon Italy, где руку не поднял почти никто из присутствующих. «Совершенно другая аудитория», — сказал он с улыбкой. Антонио уже много лет работает над производительностью Python, он общался с множеством разработчиков на Python и слышал кучу устоявшихся мифов, которые захотел развеять.

Мифы

Первый миф: «Python не медленный»; Антонио, судя по количеству поднятых рук, понял, что большинство зрителей уже знало, что это миф. Сегодня многие говорят, что скорость Python не важна, потому что это язык-клей; «сегодня важны только GPU», поэтому Python достаточно быстр. Python действительно достаточно быстр для некоторых задач, и именно поэтому им пользуются многие.

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

[Antonio Cuni]
Антонио Куни

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

Следствием утверждения «это просто язык-клей» становится утверждение «нужно просто переписать самые горячие части на C/C++», хотя оно уже немного устарело; «сегодня обычно говорят, что нужно переписывать на Rust». В этом утверждении есть доля истины, таким образом можно ускорить код, но очень быстро такой подход наткнётся на непреодолимое препятствие. Принцип Парето гласит, что 80% времени тратится на 20% кода, поэтому оптимизация этих 20% должна помочь.

Но затем программа упрётся в закон Амдала, гласящий, что улучшения по оптимизации одной части кода ограничены временем, которое тратится на уже оптимизированный код; «то, что когда-то было горячей частью, стало очень быстрым, и теперь нужно оптимизировать всё остальное». Антонио показал диаграмму, на которой некая функция inner() занимала 80% времени; если его снизить, например, в десять раз, то основное время выполнения будут теперь занимать остальные части программы.

Ещё один «миф» заключается в том, что Python медленный из-за своей интерпретируемости; да, в этом тоже есть доля истины, но это лишь в малой мере определяет медленность Python. Вот пример простого выражения на Python:

p.x * 2

Компилятор C/C++/Rust может превратить подобное выражение в три операции: загрузку значения x, умножение его на два и сохранение результата. Однако в Python должен выполниться длинный список операций, начиная с определения типа p, вызова его метода getattribute(), а затем распаковки p.x и 2 с последующей запаковкой результата, что требует распределения памяти. Ни одна из этих операций не зависит от того, интерпретируемый ли Python; эти шаги нужны из-за семантики языка.

Статические типы

Когда разработчики пользуются в Python статическими типами, они задаются вопросом: могут ли компиляторы языка пропустить все эти шаги и просто выполнять операции напрямую? Антонио привёл пример:

def add(x: int, y: int) -> int:
    return x + y

print(add(2, 3))

Однако статическая типизация не применяется принудительно в среде выполнения, поэтому для нецелочисленных типов add() можно вызывать различными способами, например:

print(add('hello ', 'world')) # type: ignore

Это совершенно валидный код, а благодаря комментарию он пройдёт проверку типов, но сложение строк выполняется не так, как для целых чисел. По словам Антонио, статические типы «совершенно бесполезны с точки зрения оптимизации и производительности». Кроме того, приведём пример ещё одного совершенно валидного кода на Python:

class MyClass:
    def __add__(self, other):
        ...

def foo(x: MyClass, y: MyClass) -> MyClass:
    return x + y

del MyClass.__add__

«Статическая компиляция Python проблематична, потому что меняться может всё».

Возможно, все наши проблемы могут решить JIT-компиляторы? По словам Куни, они могут внести серьёзный вклад в повышение скорости Python или любого другого динамического языка. Но это приводит к ещё одной, более тонкой проблеме: существует трилемма — динамический язык, скорость и простота реализации. Можно одновременно выбрать лишь два пункта, но не три.

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

Однако на практике производительность с JIT спрогнозировать оказывается сложно. На основании своего опыта разработки PyPy и консалтинговых услуг по повышению производительности Python для заказчиков, Антонио считает, что для обеспечения наилучшей производительности необходимо задумываться о том, как себя будет вести JIT. Это сложный и подверженный ошибкам процесс; в некоторых ситуациях ему не удавалось активировать оптимизации в компиляторе PyPy, потому что код был слишком сложным.

Всё это приводит к так называемой «погоне за производительностью». Допустим, сначала есть медленная программа; при оптимизации её быстрого пути выполнения мы получаем повышение скорости программы. Разработчики начинают полагаться на эту дополнительную скорость, которая может внезапно пропасть из-за, казалось бы, никак не связанным с ней изменением в другом месте программы. Антонио привёл свой любимый пример: программа работала на PyPy (она была написана на Python 2) и неожиданно стала в десять раз медленнее; оказалось, в словаре строк использовался Unicode-ключ, из-за чего JIT деоптимизировал код и всё стало гораздо медленнее.

Динамическая часть

Вот пример кода, не делающий ничего особо интересного или полезного, но демонстрирующий некоторые из проблем, с которыми сталкиваются компиляторы Python:

import numpy as np

N = 10

def calc(v: np.ndarray[float], k: float) -> float:
   return (v * k).sum() + N

Для этого кода компилятор не может сделать никаких предположений. Похоже, что он обычным образом импортирует NumPy, функция calc() умножает каждый элемент массива v на k, складывает их всех при помощи sum() , а затем прибавляет константу N. Во-первых, import может вообще не добавить NumPy; возможно, существует какой-то хук импорта, делающий нечто совершенно неожиданное. Нельзя предполагать, что N равно десяти, потому что значение может быть изменено в другом месте кода; как и в примере выше с функцией add(), декларации типов в calc() тоже не гарантированы.

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

Этот язык медленный из-за своей чрезвычайно динамической природы, но в то же время этим Python и очень удобен. Динамические возможности в 99% не нужны, но оставшийся 1% и делает Python столь потрясающим. Библиотеки часто используют паттерны, полагаясь на динамическую природу языка, чтобы создавать удобные для конечных пользователей API, поэтому от этих фич нельзя просто так отказаться.

Игра

Антонио показал «игру с компилятором», пошагово демонстрируя примеры кода, доказывающие, насколько мало компилятор может на самом деле «знать» о коде. Вот этот код, похоже, должен выдавать какую-то ошибку:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def foo(p: Point):
    assert isinstance(p, Point)
    print(p.name) # ???

Компилятор знает, что p внутри foo() — это Point, не имеющая атрибута имени. Но, разумеется, Python — это динамический язык:

def bar():
    p = Point(1, 2)
    p.name = 'P0'
    foo(p)

А вот пример того, что компилятор даже не может предполагать существование метода:

import random

class Evil:
    if random.random() > 0.5:
        def hello(self):
            print('hello world')

Evil().hello() # ??‍♂️

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

Вот ещё один пример с функцией:

def foo():
    p = Person('Alice', 16)
    print(p.name, p.age)
    assert isinstance(p, Person) # <<<

Класс Person не встречался (пока), но был пустой класс Student. В этом случае assert будет сбойным из-за определения Person:

class Person:
    def __new__(cls, name, age):
        if age < 18:
            p = object.__new__(Student)
        else:
            p = object.__new__(Person)
        p.name = name
        p.age = age
        return p

«Может существовать класс с dunder-new [например, new()], возвращающий что-то никак не связанное с этой частью и не являющееся экземпляром класса. Удачи в оптимизации всего этого».

И последний пример игры с компилятором:

N = 10

@magic
def foo():
   return N

Антонио избавил от сахара декоратор @magic и добавил несколько assert:

def foo():
   return N

bar = magic(foo)

assert foo.__code__ == bar.__code__
assert bar.__module__ == '__main__'
assert bar.__closure__ is None

assert foo() == 10
assert bar() == 20 # ??

Объект кода для foo() и bar() одинаков, но они дают разные результаты. Как можно предположить, значение N было изменено magic(); код имеет следующий вид:

def rebind_globals(func, newglobals):
    newfunc = types.FunctionType(
        func.__code__,
        newglobals,
        func.__name__,
        func.__defaults__,
        func.__closure__)
    newfunc.__module__ = func.__module__
    return newfunc

def magic(fn):
    return rebind_globals(fn, {'N': 20})

Здесь возвращается версия функции (была передана foo()), по-другому видящая значения глобальных переменных. Этот пример может показаться преувеличенным, но Антонио много лет назад писал очень похожий код для отладчика Python pdb++.

Абстрагирование

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

def algo(points: list[tuple[float, float]]):
    res = 0
    for x, y in points:
        res += x**2 * y + 10
    return

Она получает список точек, каждая из которых представлена как кортеж из чисел с плавающей запятой, и выполняет с ними вычисления. Затем Антонио вынес вычисления в отдельную функцию:

def fn(x, y):
    return x**2 * y + 10

Это уже будет медленнее первоначального кода, потому что возникает оверхед вызова функции: функцию необходимо найти, создать frame object и так далее. Здесь может помочь JIT-компилятор, но это всё равно добавит больше оверхеда. Далее Антонио сделал ещё один шаг, перейдя к классу данных Point:

@dataclass
class Point:
    x: float
    y: float

def fn(p):
    return p.x**2 * p.y + 10

def algo(items: list[Point]):
    res = 0
    for p in items:
        res += fn(p)
    return

Абстракция «из Python в C», в которой горячие пути выполнения кода пишутся на C или каком-то другом компилируемом языке, тоже подвержены дополнительным затратам. Можно представить добавление в реализации на Python всё большего количества оптимизаций, например, представления списка объектов Point в виде простого линейного массива чисел с плавающей запятой без упаковки, но если fn() будет написана для C API Python, то эти числа придётся упаковывать и распаковывать (в обоих направлениях), что будет совершенно впустую потраченным временем. В условиях современного C API этого никак нельзя избежать. Один из способов ускорения запускаемых в PyPy программ заключался в удалении кода на C и выполнении вычислений непосредственно на Python; с оптимизацией такого кода PyPy справляется хорошо.

Слон в гостиной

При обсуждении производительности Python практически никогда не упоминают «слона в гостиной»: управление памятью. В современном оборудовании вычисления очень дёшевы, но узким местом становится память. Если данные находятся на любом из уровней кэша, доступ к ним малозатратен, однако доступ к ОЗУ довольно медленный. В общем случае, для обеспечения очень высокой производительности количество промахов кэша должно быть минимальным.

Однако языку Python свойственна неудобная для кэширования структура памяти. Антонио показал это на простом примере:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = [Person('Alice', 16), Person('Bob', 21)]

У каждого Person есть два поля, которые в идеале должны размещаться в памяти рядом, и два объекта в списке тоже должны располагаться по соседству для удобства кэширования. Однако на практике, эти объекты разбросаны по памяти; это можно увидеть на визуализации из Python Tutor. Каждая стрелка — это указатель, по которому нужно следовать, то есть потенциальный промах кэша; даже для такой простой структуры данных таких стрелок почти дюжина.

Эту проблему нельзя решить просто при помощи JIT-компилятора; она нерешаема без изменения семантики. Неудобство кэширования — это неотъемлемая особенность Python. Антонио признаётся, что не знает, как решить эту проблему. Печальная правда заключается в том, что Python не может стать супербыстрым без поломки совместимости. Часть описанных выше динамических фич рано или поздно станет помехой для улучшений производительности. Если мы хотим сохранить эти фичи, то придётся смириться с невозможностью обеспечения части производительности.

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

Тем временем необходимо будет переделать систему типов с расчётом на производительность. В настоящее время типы опциональны и они не применяются принудительно, поэтому не могут использоваться для оптимизаций. Цель заключается в том, чтобы ориентированный на производительность код писался на самом Python, а не на каком-то языке, вызываемом из Python. Но для случаев, когда вызов другого языка по-прежнему предпочтителен, от дополнительных затрат (например, на упаковку) следует избавляться. Ещё важнее наше стремление к тому, что язык оставался Pythonic, потому что он нам нравится.

Куни сказал, что у него есть потенциальное решение, но оно не сделает Python быстрее, потому что, по его мнению, это невозможно. SPy, или Static Python — это созданный им несколько лет назад проект, призванный решить проблемы производительности. К SPy применимы все стандартные оговорки: «работа над ним всё ещё продолжается, проходят исследования и разработки, и мы не знаем, к чему он придёт». Самую актуальную информацию можно найти на странице GitHub по ссылке выше или в докладе о SPy на PyCon Italy.

Антонио показал небольшое демо по распознаванию границ при помощи камеры в реальном времени; оно работало в браузере с использованием PyScript. В левой части демо отображается сырой вывод камеры, а в правой части — распознавание границ, выполняемое через NumPy; NumPy достигает скорости всего в пару кадров в секунду. При переключении на алгоритм распознавания границ на основе SPy правое изображение начинает поспевать за камерой, работая с частотой примерно в 60fps. Код демо тоже выложен на GitHub.

Куни порекомендовал заинтересованным разработчикам изучить репозиторий SPy и его issue tracker; некоторые issue помечены, как «первая хорошая issue» и «требуется помощь». Также есть Discord-сервер для обсуждения проекта. Вскоре видео с докладом будет выложено на YouTube-канал EuroPython.

Комментарии (44)


  1. CryCrown
    11.08.2025 13:22

    Принцип Парето гласит, что 80% времени тратится на 20% кода, поэтому оптимизация этих 20% должна помочь.

    Разве принцип Парето говорит не об обратном? 80% кода на 20% времени. Или в программировании он действует по другому?


    1. CryCrown
      11.08.2025 13:22

      Да, я понимаю, что это не столь важно в рамках контекста статьи, но всё равно, просто любопытно


    1. cruiseranonymous
      11.08.2025 13:22

      Так он вообще не про "20% чего взять чтобы 80% результата получить", как его впаривать любят. Он про постериорное наблюдение, то есть "после того как сделали 100% и пересчитали что к чему, оказалось что...". А ещё там исходно нет где же эти заветные 20% искать, потому что такой цели и не было никогда.

      А то, что в статье - это не закон Парето(который не закон) - это анализ производительности, поиск узких мест и их опитимизация. Штука нужна, полезная, правильная. Но не Парето.


      1. CryCrown
        11.08.2025 13:22

        Понял, спасибо!


    1. me21
      11.08.2025 13:22

      Это одно и тоже. Если 80% времени тратится на 20% кода, то оставшиеся 20% времени на 80% кода ;)


      1. jankermld
        11.08.2025 13:22

        Обратный принцип Паретто)


    1. diverdm
      11.08.2025 13:22

      Одно следует из другого. И наоборот.


    1. 3263927
      11.08.2025 13:22

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


  1. dyadyaSerezha
    11.08.2025 13:22

    Динамические возможности в 99% не нужны, но оставшийся 1% и делает Python столь потрясающим.

    Почему бы не сделать некое объявление в языке, что данный код не использует динамические черты и тогда интерпретатор, JIT и ран-тайм смогут делать всё гораздо быстрее. Или наоборот, по умолчанию (для 99%) будет статика, а когда нужна динамика, надо явно это указать в коде.


    1. vadimr
      11.08.2025 13:22

      Обычно при компиляции динамических языков так и делают.

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


  1. IgnatF
    11.08.2025 13:22

    Самый большой миф тут тот, что язык в честь питона змеи назвали. На самом деле была такая группа Monty Python , вот в честь нее язык и назвали.


    1. HemulGM
      11.08.2025 13:22

      А название этой комик-группы произошло от обычного слова, означающего "питон". И это слово как означало змею (питона), так и означает. И логотип этого языка содержит изображение змеи. Так что хватит поднимать эту глупую тему


      1. Neusser
        11.08.2025 13:22

        А название змеи произошло от греческого слова Pytho (Πυθώ). И так раньше назывался город Дельфи. Так что язык питон так назван в честь языка дельфи!


        1. Moog_Prodigy
          11.08.2025 13:22

          Можно начинать писать статью с заголовком: Дельфи и Питон - как древние греки предвосхитили программирование в античности.


    1. MountainGoat
      11.08.2025 13:22

      Ага, а пакет в нём называется Python Egg потому что в той группе были одни мужики?


      1. SomeDD
        11.08.2025 13:22

        Если бы про мужиков, то было бы Python Ball(s)


  1. DX28
    11.08.2025 13:22

    Все вот говорят, что память дешева.

    Но почему-то уже не в первом проекте в крупном бизнесе на продакшене девопс даёт тебе только 2Гб на под. Ну если долго просить через СТО то расщедрится на 4 Гб. Ну и соответственно привет батчи, целые дни работы над оптимизацией и тд.


    1. MountainGoat
      11.08.2025 13:22

      У памяти есть такая бяка, что её скорость и размер накрепко связаны между собой. Это например причина, почему у массовых GPU видеопамяти сейчас только 2 размера: 8 и 16. В десктопных компах сегодня на полной скорости можно поставить только 64Гб памяти. Если поставить больше, начнутся ощутимые провалы по скорости. У серверных наверняка лучше, но всё равно пиз предел близок.


    1. ponikrf
      11.08.2025 13:22

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


  1. shlmzl
    11.08.2025 13:22

    «Если вы считаете Python медленным или недостаточно быстрым, поднимите руку»; поднялось много рук, в отличие от презентации на PyCon Italy, где руку не поднял почти никто из присутствующих. «Совершенно другая аудитория», — сказал он с улыбкой.

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


  1. BobovorTheCommentBeast
    11.08.2025 13:22

    Ну фактически, из статьи получается, что - проблемы производительности питона в том, что это питон и в его дизайне и философии. (Как в принципе и у любого динамического языка).

    Проблема скорее что из этих языков пытаются сделать универсальную тулзу и начинают лепить костыли — тайпхинты и тайпскрипты.

    Короче в воздухе витает дух статически типизированного интерпретируемого языка... (Очередного)


    1. evgenyk
      11.08.2025 13:22

      А потом будут добавлять в него динамические фишки...


      1. BobovorTheCommentBeast
        11.08.2025 13:22

        Кмк это лучше, чем в динамику докидывать статику, которая там не пришей.


  1. mk2
    11.08.2025 13:22

    Производительность в Питоне - это миф и легенда ;-)


  1. lazy_val
    11.08.2025 13:22

    Однако статическая типизация не применяется принудительно в среде выполнения

    Type hints - это не статическая типизация. Поэтому и не применяется. Это информация для линтеров разнообразных, интерпретатор и runtime про нее знать не знают.

    Вижу два варианта:

    • LLM переводила

    • LLM сочиняла


    1. BobovorTheCommentBeast
      11.08.2025 13:22

      Там в оригинале написано. Не вижу проблемы, хинты содержат исчерпывающую информацию о типе.

      Ее вполне можно дергать в рантайме.

      Pydantic вполне использует ее в рантайме.


  1. rabitagorgor
    11.08.2025 13:22

    Python: грузит данные в GPU
    GPU: считает
    Python: во, смотрите, как я быстро посчитал!


    1. leshabirukov
      11.08.2025 13:22

            Ваня (в кучерском армячке).
      Папаша! кто строил эту дорогу?
            Папаша (в пальто на красной подкладке).
      Граф Петр Андреевич Клейнмихель, душенька!
      Разговор в вагоне

      (с) Н.А, Некрасов, Железная дорога, предисловие


    1. Moog_Prodigy
      11.08.2025 13:22

      У меня был случай год назад: имеется почти 100 тысяч png картинок, для последующей обработки их нужно ресайзить, попутно выдирая информацию из тегов и складывая ее в отдельный текстовый файл. Сначала попробовал накидать скрипт для Graphick Magick - 4 картинки в секунду. Маловато. Для сравнения попробовал скормить их FS Viewer-у, берет батчем по 5 картинок и думает над ними секунды две. Ну и уже от отчаяния решил попросить ЛЛМ написать питоническую программу с нужным функционалом. 20 картинок в секунду. И это на одном ядре cpu без многопоточности. Черт его знает как оно так у него под капотом считается, но я реально офигел. Хотя во всех трех случаях с картинкой нужно было проделать всего пару операций - ресайзить (с сохранением результата в отдельной папке) и выдрать теги (у FS viever нет такого функционала). Через ту библиотеку как оказалось можно с картинками проделывать практически все то же самое, что и в GM, только сильно быстрее.


  1. yaroslavp
    11.08.2025 13:22

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


    1. BobovorTheCommentBeast
      11.08.2025 13:22

      As is true for modules, classes partake of the dynamic nature of Python: they are created at runtime, and can be modified further after creation.

      Вот и компилируй это... На глаз не специалиста - вообще непонятно что и куда компилировать, т.к. все в любой момент может поменяться.

      Другой вопрос, кому это может быть нужно и как это может вписаться даже в самые всратые и кривые практики и стандарты. Но видимо кому-то нужно. 99% это не нужно, даже если они так считают - надо дать им по башке и объяснить, что не нужно.

      Но проблему это не устранит, это суть языка. Куча всего построена вокруг этого. Это как поставить автомобиль на рельсы, оставить все органы управления и претендовать, что это тепловоз. Универсально, но и не рыба не мясо.


      1. yaroslavp
        11.08.2025 13:22

        Те проекты, что я видел в продакшоне, не используют динамичность больше, чем условный std:: variant в плюсах, они наоборот пытаются использовать костыли для внедрения статической типизации. Прикол какой-то: брать динамический язык и делать его статическим))


    1. MountainGoat
      11.08.2025 13:22

      Потому что то, что мы считаем ошибкой, правила языка не считают таковой. Утиная типизация, ё-моё. А, да, и ещё проблема давно решена: есть mypy, есть Pydantic, и есть грамотный code style.

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


  1. PepperSteep
    11.08.2025 13:22

    Вот здесь и в этом, и в прошлом, и позапрошлом году, и кучу лет подряд Питоха лидирует: https://www.tiobe.com/tiobe-index/
    Вывод: Проблема производительности питона надуманна...


    1. MountainGoat
      11.08.2025 13:22

      Вывод: хуже бредовых рейтингов только те, кто их читает.


      1. PepperSteep
        11.08.2025 13:22

        Ммм. Мы живем в симуляции и куча НПС просто так не осознано юзает питоху и гонит рейтинги, неуклонно и методично из года в год. Здравый смысл в том, что проблема производительности питона надуманна. Если бы она была и мешала, то никто бы его не юзал. Видимо плюсы перекрывают не существенные минусы...


  1. cdriper
    11.08.2025 13:22

    self.name = name

    скорее всего это будет плохо работать (в плане локальности данных) даже в "супер быстрых" языках типа C++

    потому что name это что-то типа std::string и непосредственно за стороковыми данными нужно ходить по указателю в какое-то случайное место в куче


  1. johnsqurrel
    11.08.2025 13:22

    обсуждать производительность питона не упоминая GIL ? знаем, умеем, практикуем.


    1. Nemoumbra
      11.08.2025 13:22

      Окей, производительность однопоточного питона. По-моему, самое интересное именно тут. В особенности большие списки примеров, которые показывают, как сложно компилировать питон (это мне доставляет такое же удовольствие, как и книга "контрпримеры в анализе").


      1. HemulGM
        11.08.2025 13:22

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


        1. PepperSteep
          11.08.2025 13:22

          В Питоне есть и потоки и процессы (в обход GIL на разных ядрах) и прямой доступ к памяти (SharedMemory). В крупномасштабном проекте интерпретатор простаивает больше в ожиданиях завершения файловых и сетевых операций. Нету проблем производительности в питоне, от слова СОВСЕМ.


          1. HemulGM
            11.08.2025 13:22

            Есть у Питона проблемы с производительностью. Достаточно сравнить в цикле простые математические операции с другим языком. И речь тут не о потоках, которым GIL мешает.

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

            В крупномасштабном проекте интерпретатор простаивает больше в ожиданиях завершения файловых и сетевых операций

            А это тут вообще не при чем. Это никак не касается вопроса производительности языка.


            1. PepperSteep
              11.08.2025 13:22

              Вы путаете проблему производительности со скоростью выполнения синтетических тестов. Я утверждаю, что на практике, - нет проблемы производительности языка, что она надуманна и не стоит обсуждения. Никому эти синтетические тесты не нужны (чё бы тогда не сравнивать с ассемблером, и говорить что у C++ есть проблемы производительности??)
              Я говорю что проблемы производительности при практическом использовании питона нету или она не существенна.
              Еще раз. вот доказательство моих слов: https://www.tiobe.com/tiobe-index/


  1. PavelKuptsov
    11.08.2025 13:22

    Антонио сказал, Антонио писал...
    Слишком много частностей