Почему% 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  

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() подходит, если у вас есть последовательность строк переменного размера и / или вы хотите объединить несколько строк с одним и тем же разделителем.


2

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.