Есть ли разница в эффективности между использованием "+" и "," в print()?
Я только заметил, что если я использую +
для конкатенации в функции print()
и запускаю код в оболочке, текст появляется быстрее. Принимая во внимание, что при использовании ,
текст выглядит намного медленнее, как если бы с эффектом анимации "набрал".
Есть ли разница в эффективности между этими двумя?
Ответы
Ответ 1
edit: Кажется, вопрос был не столько в характере операций, сколько в их скорости, о чем не говорится в этом ответе!
Разница заключается в том, что при +
вы используете конкатенацию для создания более крупной строки для перехода к функции print
, а при ,
вы передаете несколько строк функции print
. Обратите внимание, что это поведение не является особенным для функции print
: конкатенация - это всего лишь метод в строках, а запятая всегда используется для разделения аргументов функции.
Например, используя конкатенацию:
print('hello' + ' ' + 'world')
Это первое объединяет три строки в форме 'hello world'
, а затем печатает это.
При использовании нескольких аргументов:
print('hello', 'world')
Это передает две строки функции print
. Как вы можете прочитать здесь, функция print
принимает один или несколько объектов в качестве аргументов и печатает их, разделенные другим аргументом, sep
, который по умолчанию является пространством. Таким образом, это дает тот же результат, что и предыдущий пример.
Обратите внимание, что любое количество аргументов может быть передано функции print
и что эти аргументы сами по себе могут быть объединенными строками:
print('i' + ' ' + 'want', 'to', 'print', 'some', 'strings')
Приятная часть состоит в том, что вы можете указать аргумент sep
для изменения поведения:
print('mary', 'peter', 'bob', sep=' and ')
Результат: mary and peter and bob
Ответ 2
Хотя я бы не стал подозревать большое несоответствие между ними, они, очевидно, немного отличаются друг от друга.
A print
вызов, который объединяет литеральные строки, может быть объединен оптимизатором подписи CPython перед печатью, что приводит к более быстрому исполнению, возможно, это то, что вы видите. Кроме того, с небольшими строками, тот факт, что передан только один аргумент, и в результате sep
не используется, также является небольшим преимуществом.
При использовании больших строк необходимость создания большой временной строки для их конкатенации отрицает достигнутые разности скорости. (Тот факт, что sep
не используется и передается только один аргумент, сбивается из-за размера и их конкатенации)
Использование ,
в вызове печати передает каждую строку в качестве аргумента и разделяет ее, используя значение по умолчанию sep
. Хотя для этого, очевидно, требуется немного больше работы, это постоянная работа, которая снова исчезает, когда задействованы большие строки.
Итак, с небольшими строками, которые фактически попадают в оптимизатор, конкатенация выполняется немного быстрее:
%timeit print("a" + "b", file=f)
1000000 loops, best of 3: 1.76 µs per loop
%timeit print("a", "b", sep='', file=f)
100000 loops, best of 3: 2.48 µs per loop
Даже если оптимизатор не может присоединиться к ним:
a = "a"; b = "b"
%timeit print(a + b, file=f)
1000000 loops, best of 3: 2 µs per loop
%timeit print(a, b, sep='', file=f)
100000 loops, best of 3: 2.45 µs per loop
когда размеры строк увеличиваются, эта небольшая разница затмевается:
s1, s2 = "s" * 100000, "s"*100000
%timeit print(s1 + s2, file=f)
1000 loops, best of 3: 374 µs per loop
%timeit print(s1, s2, sep='', file=f)
1000 loops, best of 3: 373 µs per loop
Ответ 3
Очевидное различие заключается в том, что print(a, b)
поместит разделитель (по умолчанию - одно пространство) между значениями a
и b
, а print(a + b)
не будет. Я бы предпочел, чтобы версия с запятой была быстрее, поскольку для версии с плюсом требуется создание новой строки.
Обновление:, используя следующий код:
import timeit
t1 = timeit.timeit('print("aa", "bb")')
t2 = timeit.timeit('print("aa" + " " + "bb")')
print(t1, t2)
У меня есть 9.997510432032868 11.018277243943885
т.е. разница в 10% в пользу запятой; но используя несколько более длинные строки:
t1 = timeit.timeit('print("aaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbb")')
t2 = timeit.timeit('print("aaaaaaaaaaaaaaa"+" "+"bbbbbbbbbbbbbbbb")')
опрокинул весы: 18.56978454696946 18.07760854391381
. Затем я перенаправил вывод в файл и получил еще более интересные результаты:
0.730336288921535 0.39260527514852583
для более коротких и 0.7751083469484001 0.5140565759502351
для более длинных строк. По-видимому, на результаты в большей степени влияет скорость прокрутки моего терминала, чем на код Python.
Ответ 4
print(a + b + c)
, оценивает выражение и передает один аргумент для печати. Второй, print(a, b, c)
, просто передает три аргумента для печати. Это почти то же самое, что и выход из печати. Второй не выполняет никаких конкатенаций и просто выводит каждое значение, разделенное пробелом (которое является по умолчанию по умолчанию).
плюс в выражении выполняет конкатенацию, но запятая не выполняет конкатенацию.
Конкатенация создает каждую строку в памяти, а затем объединяет их вместе в конце в новой строке (так что это может быть не очень дружественным к памяти), а затем печатает их на ваш вывод на том же время
Ответ 5
+
может использоваться со строками для конкатенации 2 строк. Однако в python 2.X ,
используется в печати для печати строки inline, но в python 3.X, если вы помещаете ,
между двумя элементами, компилятор преобразует два элемента в кортеж. При использовании внутри печати +
используется для конкатенации и, следовательно, они печатаются вместе. но с помощью ,
печатает их с пробелом, поскольку он печатает 2 элемента кортежа.
например,
In [1]: print('abcd'+'pqrs')
abcdpqrs
In [2]: print('abcd','pqrs')
abcd pqrs
In [3]: x=('abcd'+'pqrs')
In [4]: y=('abcd','pqrs')
In [5]: x
Out[5]: 'abcdpqrs'
In [6]: y
Out[6]: ('abcd', 'pqrs')
In [7]: type(y)
Out[7]: tuple
In [8]: type(x)
Out[8]: str
Ответ 6
Если вы используете оператор +
, в конце создания всей строки, и только после этого он будет напечатан, а ,
он будет создан по частям и напечатан. И, как уже было сказано много пользователей, есть еще один фактор, конкат "белого" пробела, он также требует времени.
Ответ 7
Вы также можете взглянуть на байт-код для использования dis
.
import dis
def f1():
print('Hello ' + 'world!')
def f2():
print('Hello', 'world!')
print(dis.dis(f1))
62 0 LOAD_GLOBAL 0 (print)
3 LOAD_CONST 3 ('Hello world!')
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
None
print(dis.dis(f2))
66 0 LOAD_GLOBAL 0 (print)
3 LOAD_CONST 1 ('Hello')
6 LOAD_CONST 2 ('world!')
9 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
None
Вы можете видеть, что print
с запятыми вызывает LOAD_CONST
дважды в этом случае (или столько раз, сколько есть переменные\строки). Это указывает на то, что конкатенация быстрее и будет постепенно ускоряться, чем больше строк вы объединяете, либо разделяете запятыми.