Чому% 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, який використовує рядок формату, щоб створити рядок входу в журнал ліниво ( logging.info("blah: %s", 4)). Це відмінно підходить для підвищення продуктивності, якщо бібліотека журналів вирішила, що поточний запис журналу буде відкинутий фільтром журналу, тому йому не потрібно форматувати рядок.


31
у вас є якесь наукове чи емпіричне джерело для №1? Тому що я думаю, що це набагато менш читабельно (особливо з більш ніж двома-трьома аргументами)
Ловіс

4
@ L.Möller: Я не зовсім впевнений, якого джерела ви очікуєте від того, що в кінцевому підсумку є суб'єктивним досвідом (простота читання), але якщо ви хочете, щоб мої міркування: 1)% s вимагає 2 додаткових символів на кожного заповнювача та + вимагає мінімум 4 (або 8, якщо ви дотримуєтесь PEP8, 13, якщо ви примушуєте), 2)% s укладено в одну рядок, тому простіше проаналізувати візуально, з +, у вас є більше рухомих частин: закриття рядка, оператор, змінна , оператор, відкрита рядок, 3) забарвлення синтаксису% s має один колір для кожної функції: рядок і заповнювач, з + ви отримуєте три забарвлення: рядок, оператор та змінне забарвлення.
Лежать Раян

4
@ L.Möller: 4) У мене є можливість розміщувати рядки довшого формату в змінну чи словник, подалі від місця, де потрібно форматування; те ж саме не можна сказати з конкатенаціями. Але так, я також не використовував би% s, коли у мене більше 4-5 речей для інтерполяції, замість цього я використовував би варіант (varname) s або формат "{foo}". Формат () у Python. Я думаю, що явні назви покращують читабельність для довших рядків формату з великою кількістю інтерпольованих змінних.
Лі Лі Райан

2
Я не знаю, що таке "правда", тому я прошу, чи є у вас докази :-). Дійсно згоден з вашим другим коментарем
Ловіс

6
Я вважаю, що №2 є підозрюваним - чи є у вас підтверджені документи? Я не дуже знайомий з Java, але в C # конкатенація швидша, ніж інтерполяція рядків . Я повністю погоджуюся з №1 і дуже покладаюся на те, що для того, щоб вирішити, коли використовувати, але ви повинні пам’ятати, що інтерполяція вимагає кількості синтаксичного розбору та складності, коли конкатенація нічого з цього не вимагає.
Джиммі Хоффа

48

Я єдиний, хто читає зліва направо?

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

Що з них швидше зрозуміло?

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

або

"your " + object + " is in the " + location  

17
Очевидно, що це суб’єктивно, оскільки я вважаю перше ще читабельнішим - і простіше писати та редагувати. Другий переплутує текст з кодом, який затемнює обидва і додає шум. Наприклад, легко помилитися пробілами у другій.
ЖакБ

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
Я не погоджуюся з вашим першим твердженням, але ми можемо погодитися з різницею, я ось-ось збирався опублікувати відповідь у відповідь на ваше друге, так що підтверджую
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.