Почему% s лучше чем + для конкатенации?

88

Я понимаю, что мы должны использовать %sдля объединения строк, а не +в Python.

Я мог сделать любое из:

hello = "hello"
world = "world"

print hello + " " + world
print "%s %s" % (hello, world)
print "{} {}".format(hello, world)
print ' '.join([hello, world])

Но почему я должен использовать что-то кроме +? Быстрее написать объединение с простым +. Затем , если вы посмотрите на строку форматирования, можно указать типы , например , %sи %dи такие. Я понимаю, что может быть лучше четко указать тип.

Но потом я прочитал, что +следует избегать использования конкатенации, хотя ее проще набирать. Есть ли четкая причина, по которой строки должны объединяться одним из этих других способов?

Никлас Розенкранц
источник
29
Кто тебе сказал, что лучше?
Яннис
3
%sне для конкатенации, это спецификация преобразования для форматирования строк, полученная из Си printf(3). Существуют случаи для использования этого или оператора конкатенации; то, что вы используете, должно основываться на оценке ситуации, а не на догме. Насколько легко написать код, совершенно не имеет значения, потому что вы собираетесь сделать это только один раз.
Blrfl
Я перефокусировал вопрос только на python (хотя я не питон, и в коде все еще могут быть глюки). Пожалуйста, убедитесь, что это вопрос, который вы задаете, внесите соответствующие изменения и рассмотрите возможность задать другой вопрос, если вы заинтересованы в C или Java.
12
И теперь у нас есть превосходные f-струны ! print(f"{hello} {world}"), имеет читабельность конкатенации, поскольку переменные видны там, где они встречаются в строке, и быстрее, чем str.format.
Энрико Борба

Ответы:

88
  1. Читаемость. Синтаксис строки формата более читабелен, поскольку он отделяет стиль от данных. Кроме того, в Python %sсинтаксис будет автоматически приводить любые не- strтипы к str; в то время как конкатенация работает только с str, и вы не можете объединить strс int.

  2. Представление. В Python strявляется неизменным, поэтому левая и правая строки должны быть скопированы в новую строку для каждой пары конкатенации. Если вы объедините четыре строки длиной 10, вы будете копировать (10 + 10) + ((10 + 10) +10) + (((10 + 10) +10) +10) = 90 символов вместо всего 40 персонажи. И все становится квадратично хуже с увеличением числа и размера строки. В некоторых случаях Java оптимизирует этот случай, трансформируя серию конкатенаций в использование StringBuilder, но CPython этого не делает.

  3. В некоторых случаях библиотека ведения журнала предоставляет API, который использует строку формата для создания строки записи журнала lazily ( logging.info("blah: %s", 4)). Это здорово для повышения производительности, если библиотека журналов решила, что текущая запись журнала будет отброшена фильтром журнала, поэтому ей не нужно форматировать строку.

Ли Райан
источник
31
Есть ли у вас какой-либо научный или эмпирический источник № 1? Потому что я думаю , что это гораздо гораздо менее читаемым (особенно с более чем 2 или три аргумента)
Ловис
4
@ L.Möller: Я не совсем уверен, какой источник вы ожидаете от субъективного опыта (простота чтения), но если вы хотите мои рассуждения: 1)% s требует 2 дополнительных символа на каждый заполнитель, а + требует минимум 4 (или 8, если вы следуете PEP8, 13, если вы принудительно), 2)% s заключен в одну строку, так что проще анализировать визуально, с +, у вас есть больше движущихся частей: строка закрытия, оператор, переменная , оператор, открытая строка, 3) синтаксическая раскраска% s имеет один цвет для каждой функции: строка и заполнитель, с + вы получите три раскраски: строку, оператор и переменную раскраску.
Ли Райан
4
@ L.Möller: 4) У меня есть возможность помещать более длинные строки формата в переменную или словарь, вдали от места, где необходимо выполнить форматирование, 5) строка формата может быть указана пользователем из файла конфигурации, командных аргументов или базы данных. То же самое нельзя сказать о конкатенациях. Но да, я бы также не использовал% s, когда у меня есть более 4-5 вещей для интерполяции, вместо этого я бы использовал вариант% (varname) s или "{foo}". Format () в Python. Я думаю, что явные имена улучшают читаемость для длинных строк формата с большим количеством интерполированных переменных.
Ли Райан
2
Я не знаю, что "правда", поэтому я спрашиваю, есть ли у вас доказательства :-). Действительно согласен с вашим вторым комментарием
Lovis
6
Я считаю № 2 подозреваемым - у вас есть документальное подтверждение? Я не очень хорошо знаком с Java, но в C # конкатенация выполняется быстрее, чем интерполяция строк . Я полностью согласен с # 1 и действительно полагаюсь на то, что для решения, когда использовать какой, но вы должны помнить, что интерполяция требует некоторого разбора строк и сложности, где конкатенация не требует ничего из этого.
Джимми Хоффа
48

Я единственный, кто читает слева направо?

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

Что из этого яснее с первого взгляда?

"your %s is in the %s" % (object, location)

или же

"your " + object + " is in the " + location  
Mawg
источник
17
Очевидно, что это субъективно, так как я нахожу первый более читабельным - и его легче писать и редактировать. Второй смешивает текст с кодом, который затемняет и добавляет шум. Например, легко ошибиться во втором.
JacquesB
5
@JacquesB Я действительно думаю, что ваш мозг настолько знаком с этим форматом, что вы сразу же переходите к скобкам и мгновенно заменяете слова. Технически это не чтение слева направо, но это прекрасно. Я тоже так поступаю, так что да, 1 легче читать, потому что я знаю, что мне приходится иметь дело с глупыми пробелами до и после кавычек во второй, и с этим действительно медленно работать.
Нельсон
3
Спустя nдесятилетия мой ум тоже работает таким образом ;-) Но я все еще поддерживаю свой ответ, второй яснее и проще для чтения, поэтому его нужно поддерживать. И это становится более очевидным, чем больше у вас параметров. В конце концов, если это шоу для одного человека, следуйте тому, с чем вы знакомы и с которым вам удобно; если это командная работа, обеспечить согласованность и проверку кода; люди могут привыкнуть к любому.
Mawg
4
Первый способ более читабелен для меня, потому что в середине предложения он содержит меньше «беспорядка». Моему глазу легче заглянуть в конец, тогда как мой мозг должен разобрать лишние кавычки, пробелы и плюсы. Конечно, теперь я предпочитаю Python строки формата 3,6: f"your {object} is in the {location}".
Дастин Уайатт
8
Я также нахожу, что еще труднее читать и писать, когда переменная сама должна быть заключена в кавычки. "your '" + object + "' is in the '" + location + "'"... Я даже не уверен, понял ли я это прямо сейчас ...
Дастин Уайетт
12

Пример, поясняющий аргумент читабельности:

print 'id: ' + id + '; function: ' + function + '; method: ' + method + '; class: ' + class + ' -- total == ' + total

print 'id: %s; function: %s; method: %s; class: %s --total == %s' % \
   (id, function, method, class, total)

(Обратите внимание, что второй пример не только более читабелен, но и проще в редактировании, вы можете изменить шаблон в одной строке и список переменных в другой)

Отдельная проблема заключается в том, что код% s также конвертируется в строку, в противном случае вам придется использовать вызов str (), который также менее читабелен, чем код% s.

дождливый
источник
1
Я не согласен с вашим первым утверждением, но мы можем согласиться с тем, что я не согласен, я как раз собирался опубликовать ответ в соответствии с вашим вторым, так что upvote
Mawg
6

Использование +следует не избегать вообще. Во многих случаях это правильный подход. Использование %sили .join()являются предпочтительными только в особых случаях, и это обычно совершенно очевидно, когда они являются лучшим решением.

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

%sили .format()полезны, если вы хотите интерполировать строки или значения в середине большей строки. Пример:

print "Hello %s, welcome to the computer!" % name

В этом случае %sего использование будет более читабельным, поскольку вы не будете разбивать первую строку на несколько сегментов. Особенно, если вы интерполируете несколько значений.

.join() подходит, если у вас есть последовательность строк переменного размера и / или вы хотите объединить несколько строк с одним и тем же разделителем.

JacquesB
источник
2

Поскольку порядок слов может меняться на разных языках, форма с %sобязательна, если вы хотите правильно поддерживать перевод строк в вашем программном обеспечении.

martjno
источник