Ответ 1
В целом, стандарт языка Python здесь не дает никаких гарантий; на самом деле, как определено, строки являются неизменяемыми, и то, что вы делаете, должно укусить вас в любом случае, так как вы написали форму алгоритма Шлемьеля Пейнтера.
Но в первом случае, как деталь реализации, CPython (справочный интерпретатор) поможет вам и объединит строку на месте (технически нарушая гарантию неизменности) при некоторых довольно специфических условиях, которые позволяют ему придерживаться духа правила неизменности. Наиболее важным условием является то, что на конкатенируемую строку следует ссылаться только в одном месте (если это не так, другая ссылка будет меняться на месте, нарушая внешний вид str
являющегося неизменным). str2 = str1
после каждой конкатенации, вы гарантируете, что при конкатенации есть две ссылки, поэтому при каждой конкатенации необходимо создавать новую str
чтобы сохранить кажущуюся неизменность строк. Это означает больше выделения и освобождения памяти, большее (и постепенно увеличивающееся) количество копий памяти и т.д.
Обратите внимание, что полагаться на эту оптимизацию явно не рекомендуется в PEP 8, руководстве по стилю Python:
Код должен быть написан так, чтобы не мешать другим реализациям Python (PyPy, Jython, IronPython, Cython, Psyco и т.д.).
Например, не полагайтесь на эффективную реализацию CPython конкатенации строк на месте для операторов в форме
a += b
илиa = a + b
. Эта оптимизация хрупка даже в CPython (она работает только для некоторых типов) и совсем не присутствует в реализациях, которые не используют пересчет. В чувствительных к производительности частях библиотеки следует использовать форму''.join()
. Это будет гарантировать, что конкатенация происходит в линейное время в разных реализациях.
Важное замечание о том, что "работает только для некоторых типов". Эта оптимизация относится только к str
; в Python 2 он не работает на unicode
(хотя Python 3 str
основан на реализации unicode
Python 2), а в Python 3 он не работает на bytes
(которые похожи на Python 2 str
под капотом),