Pull to refresh

Comments 35

Для большинства языков свойственно - вызов функции медленнее чем вызов конструкции языка. Но с такими вещами по хорошему должен оптимизатор справляться.

В данном случае происходит ровно то, что и должно - вызов функции. И оптимизировать его будет некорректно, потому что никто не мешает написать list = tuple, например. Или свой супер-конструктор объекта, мимикрирующего под список. И интерпретатор байт-кода должен будет выполнить именно его, для чего внутри и нужно сделать честный вызов по имени.

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

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

как лучше реализовать этот механизм в пайтоне

В пайтоне это реализовать невозможно. Или у вас есть идеи, как в компиляторе проанализировать, например,


такое?
def happy_debugging_losers():
    import base64
    with open('tmp.txt', 'w') as wfp:
        wfp.write('b64decodeX19idWlsdGluc19fLmxpc3Q9dHVwbGUK')
    with open('tmp.txt', 'r') as rfp:
        n = rfp.read(9)
        exec(getattr(base64, n)(rfp.read()))

print(type(list()))  # <class 'list'>
happy_debugging_losers()
print(type(list()))  # <class 'tuple'>

list() - ладно. Больше печалит необходимость в диктах заключать ключи в кавычки. У {} vs dict() такие же отличия в производительности, но когда надо просто создать большой словарь, обычно юзаю dict().

Интересно бы взглянуть на байт-код для dict и {}. Но наверняка там такая же история и dict вызывается как функция с kwarg, которые не требуют кавычек по своей природе.

При создании через {} ключом может быть и отличный от строки тип, поэтому автоматически конвертировать в неё нельзя.

Важнее тут не столько константы различных типов, сколько возможность указать в качестве ключа переменную:

{k+1: v*2 for k, v in d.items()}

печалит необходимость в диктах заключать ключи в кавычки

Как тогда отличить переменную от значения ключа?

Как в JS: mydict.key или {key: val} - всегда строка, а название ключа надо из переменной брать, то mydict[var].

И делать тридцать миллионов императивных присвоений вместо краткого лаконичного {}?

Немного не понял про тридцать миллионов. Можно пример?

В js все же можно использовать переменные в объявлении объекта - надо обернуть переменную в []. Т.е. {[foo]: 'bar'}

Но в питоне ключ не всегда строка.

Я в конце предложения привёл пример с переменной - `mydict[keyname]`.

Так там же вроде издавна у [] обычные динамические массивы были, которые время только на реалокации тратили, а list был структурой более нетривиальной, который мог в некоторых случаях быть оптимизирован до такого же массива, типа того же случая со статичными данными, но в общем случае проигрывал на накладных расходах.

А что скажете про несколько способов форматирования строк? :)

Интересно, а сколько их всего? Я вот так сходу пяток насчитал.

  • проценты 'foo %s' % 'bar'

  • тупо в лоб вот так 'foo' + 'bar'

  • метод формат 'foo {}'.format('bar')

  • f-строки f'foo {bar!r}'

  • шаблоны string.Template

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

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

P.S: Мне тут пару месяцев пришлось ковыряться с JS, так Python после этого как глоток свежего воздуха.

Это же очевидно, что нужно f-strings использовать, а когда они не решают задачу, использовать более очевидное решение. :)

- f-string форматировать здесь и сейчас
- str.format переиспользуемый шаблон или старый питон
- % логирование или очень старый питон.

and preferably only one

И я думаю говорится про оптимальный вариант. Присвоевание может быть и такое
a = 2
b = 0

while b!=a:
b = random.randint(-100,100);

тоже очевидный, но...

Мне кажется, что этот постулат потерял актуальность практически сразу.

UFO just landed and posted this here

Тот случай когда использую для создания списков [ ] тупо потому что на list() ругается pylint вот таким R1734: Consider using [] instead of list() (use-list-literal).

upd: сейчас увидел, что в доке пайлинта как раз написано про скорость исполнения:

Emitted when using list() to create an empty list instead of the literal []. The literal is faster as it avoids an additional function call.

Любая статья "что быстрее в питоне" вызывает недоумение, потому что и так медленно, и так медленно, и если кого-то начинает волновать скорость создания списка в питоне, то этот человек ошибся языком программирования. Потому что в быстрых языках программирования константный массив создаётся за 0 наносекунд. Почему? Потому что он уже в .data или .rodata, готовый.

Когда-то я тоже таким занимался, помню в php цикл for оказался в 1,3 раза медленнее чем while Это логично. Думаю go to юыл бы еще быстрее! Но читабельность! Языки ведь для этого и придумывали...

Бегло пролистал, питон только учу, а на какой версии питона данные?

Подпишите, пожалуйста, оси на графике. Не понятно что означают числа по оси Y: чем больше - тем быстрее или наоборот?

Ось Y - время в секундах. Чем больше времени, чем выше график, тем больше времени нужно, тем дольше работает код, т.е. медленнее.

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

Напомнило:

- Я использую С потому что он быстрее всех

- Но ведь твой проект будет работать аналогично и на других языках

- ЗАТКНИСЬ, ЗАТКНИСЬ

Но пост хорош, читать интересно))

Спасибо! Как раз недавно задавался этим вопросом. Подскажите, правильно ли я понимаю, что с созданием словарей ситуация обстоит так же?

Если не придираться к деталям, то так же.

Sign up to leave a comment.

Articles