Является ли конкатенация строк python += плохой практикой?

Я читаю Автостопом по Python и есть короткий фрагмент кода

foo = 'foo'
bar = 'bar'

foobar = foo + bar  # This is good
foo += 'ooo'  # This is bad, instead you should do:
foo = ''.join([foo, 'ooo'])

Автор указал, что ''.join() не всегда быстрее, чем +, поэтому он не против использования + для конкатенации строк.

Но почему foo += 'ooo' считается плохой практикой, а foobar=foo+bar считается хорошей?

  • foo += bar хорошо?
  • foo = foo + 'ooo' хорошо?

Перед этим фрагментом кода автор написал:

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


person nos    schedule 24.09.2016    source источник
comment
@jonrsharpe: этот вопрос на самом деле не распространяется на один случай расширенного присваивания вне цикла. Честно говоря, я очень удивлен этим заявлением в руководстве, потому что между foo + bar и foo += bar нет технической разницы, но, видимо, для foo += 'ooo' она есть..   -  person Martijn Pieters    schedule 24.09.2016
comment
@jonrsharpe: я думаю, что это не дубликат. Там проблема в скорости + по сравнению с ''.join(). Здесь сравниваются два способа использования +.   -  person nos    schedule 24.09.2016
comment
Я думаю, что причина в руководстве заключается в том, что для строки creation str.join() не всегда лучше, foobar = ''.join(foo, bar) на самом деле не лучше, чем foobar = foo + bar. Если вы посмотрите на весь контекст из утверждения более ясно, что оно упоминается как исключение для рекомендации, что join() предпочтительнее += в большинстве случаев. Приведенный пример, вероятно, можно было бы улучшить.   -  person mata    schedule 24.09.2016
comment
foo = ''.join([foo, 'ooo']) в этом примере кажется слишком чрезмерным. Он не только хуже читается, но и в 100 раз медленнее, чем другие примеры, согласно некоторым тестам с модулем timeit.   -  person Ted Klein Bergman    schedule 24.09.2016
comment
Я не вижу ничего изначально неправильного в foo += 'ooo'... Важно отметить, что автор «Руководства для автостопщиков» говорит о хорошем и плохом с точки зрения производительности: гораздо эффективнее собирать части в список , который можно изменить, а затем склеить («объединить») части вместе, когда потребуется полная строка   -  person Carlos Mermingas    schedule 24.09.2016
comment
что читабельнее. Присоединяйтесь к множеству предметов, + к двум.   -  person Paul Collingwood    schedule 24.09.2016
comment
Вам нужно прочитать Почему ''.join() быстрее, чем += в Python   -  person vishes_shell    schedule 24.09.2016


Ответы (2)


Это плохая практика?

Разумно предположить, что это неплохая практика для этого примера, потому что:

  • Автор не дает никаких оснований. Может быть, это просто не нравится ему/ей.
  • В документации Python не упоминается о плохой практике (из того, что я видел).
  • foo += 'ooo' так же читаем (по моему мнению) и примерно в 100 раз быстрее, чем foo = ''.join([foo, 'ooo']).

Когда следует использовать один над другим?

Недостатком конкатенации строк является необходимость создания новой строки и выделения новой памяти для каждой конкатенации! Это отнимает много времени, но не так уж важно, если несколько и небольшие строки. Когда вы знаете количество строк для конкатенации и вам не нужно больше, чем 2-4 конкатенации, я бы пошел на это.


При объединении строк Python должен выделить новую память только для конечной строки, что намного эффективнее, но для вычисления может потребоваться больше времени. Кроме того, поскольку строки неизменяемы, часто более практично использовать список строк для динамического изменения и преобразовывать его в строку только при необходимости.

Часто бывает удобно создавать строки с помощью str.join(), так как для этого требуется итерация. Например:

letters = ", ".join("abcdefghij")

Заключить

В большинстве случаев имеет смысл использовать str.join(), но бывают случаи, когда конкатенация так же жизнеспособна. Использование любой формы конкатенации строк для огромных или многих строк было бы плохой практикой, так же как использование str.join() было бы плохой практикой для коротких и немногих строк, по моему собственному мнению.

Я считаю, что автор просто пытался создать эмпирическое правило, чтобы легче было определить, когда что использовать, не вдаваясь в подробности и не усложняя.

person Ted Klein Bergman    schedule 24.09.2016
comment
", ".join(name for name in school) такое же, как ", ".join(school), дополнительное выражение генератора не улучшает читабельность, а только делает его менее эффективным. Если вам не нужно обрабатывать name (модифицировать, фильтровать, индексировать, ...), нет причин использовать выражение генератора - person mata; 25.09.2016
comment
Да, вы абсолютно правы! Это была ошибка с моей стороны, и я изменю пример. - person Ted Klein Bergman; 25.09.2016
comment
@TedKleinBergman, ", ".join(range(10)), вероятно, не лучший пример, так как он потерпит неудачу ... - person Jon Clements♦; 25.09.2016
comment
@JonClements Да, я не знаю, о чем я думал. Я немного занят/напряжен в данный момент, но я обязательно добавлю лучший пример позже - person Ted Klein Bergman; 25.09.2016
comment
@TedKleinBergman, не беспокойтесь... может быть, покажите это, используя letters = ', '.join('abcdefghij') или что-то в этом роде... понятно... - person Jon Clements♦; 25.09.2016
comment
@JonClements Это отличный пример! Быстро добавит. Спасибо! - person Ted Klein Bergman; 25.09.2016

Если количество строк невелико, а строки известны заранее, я бы пошел:

foo = f"{foo}ooo"

Использование f-строки. Однако это справедливо только с версии python 3.6.

person LittleFox    schedule 10.05.2021
comment
Вопрос не в том, как объединить строки. Речь шла о том, почему это foo += 'ooo' плохая практика. - person Gino Mempin; 11.05.2021
comment
Это не дает ответа на вопрос. Получив достаточную репутацию, вы сможете /comment">прокомментировать любой пост; вместо этого дайте ответы которые не требуют разъяснений от спрашивающего. – Из обзора - person sjaustirni; 11.05.2021