Это дубликат Python-эквивалента Java StringBuffer . ВНИМАНИЕ: ответы здесь устарели и, по сути, вводят в заблуждение. Посмотрите этот другой вопрос, чтобы получить ответы, которые более актуальны для современных версий Python (обязательно 2.7 и выше).
Построение длинных строк на языке программирования Python может иногда приводить к очень медленному выполнению кода. В этой статье я исследую вычислительную производительность различных методов конкатенации строк.
Обратите внимание, что эта статья написана на основе Python 2.2. В современной версии Python тесты, скорее всего, будут выглядеть несколько иначе (CPython обычно успешно оптимизирует конкатенацию, но вы не хотите зависеть от этого в важном коде), и выражение генератора, в котором он использует понимание списка, заслуживает рассмотрения ,
Майк Грэм,
4
Было бы неплохо выделить некоторые основные моменты в этой статье, по крайней мере, пару реализаций (чтобы избежать проблем с гниением ссылок).
jpmc26
3
Метод 1: resultString + = appendString - самый быстрый согласно тестам @ Antoine-tran ниже
Justas
5
Ваша цитата вовсе не отвечает на вопрос. Включите соответствующие части в сам ответ, чтобы соответствовать новым правилам.
Иск Фонда Моники
27
Я использовал код Оливера Кроу (ссылка предоставлена Эндрю Хейром) и немного адаптировал его для адаптации Python 2.7.3. (с использованием пакета timeit). Я работал на своем персональном компьютере, Lenovo T61, 6 ГБ ОЗУ, Debian GNU / Linux 6.0.6 (сжатие).
Вот результат для 10000 итераций:
method1: 0,0538418292999 секунд
размер процесса 4800 кб
method2: 0,22602891922 секунды
размер процесса 4960 кб
method3: 0,0605459213257 секунд
размер процесса 4980 кб
method4: 0,0544030666351 сек.
размер процесса 5536 кб
method5: 0,0551080703735 секунд
размер процесса 5272 кб
method6: 0,0542731285095 секунд
размер процесса 5512 кб
и для 5 000 000 итераций (метод 2 был проигнорирован, потому что он работал слишком медленно, как всегда):
method1: 5,88603997231 сек
размер процесса 37976 кб
method3: 8.40748500824 секунды
размер процесса 38024 кб
method4: 7.96380496025 секунд
размер процесса 321968 кб
method5: 8.03666186333 секунд
размер процесса 71720 кб
method6: 6.68192911148 секунд
размер процесса 38240 кб
Совершенно очевидно, что разработчики Python проделали отличную работу по оптимизации конкатенации строк, и, как сказал Хоар, «преждевременная оптимизация - это корень всех зол» :-)
Это не преждевременная оптимизация, чтобы избежать хрупких оптимизаций, зависящих от интерпретатора. Если вы когда-нибудь захотите выполнить портирование на PyPy или рискуете столкнуться с одним из множества скрытых случаев сбоя при оптимизации, делайте все правильно.
Veedrac 03
1
Похоже, компилятору проще оптимизировать метод 1.
mbomb007
25
Полагаться на оптимизацию компилятора хрупко. Контрольным показателям, указанным в принятом ответе, и цифрам, приведенным Антуаном-Траном, нельзя доверять. Эндрю Хэйр совершает ошибку, включая обращение к reprсвоим методам. Это в равной степени замедляет работу всех методов, но скрывает реальный ущерб при построении строки.
Используйте join. Это очень быстро и надежно.
$ ipython3
Python3.5.1(default,Mar22016,03:38:02)IPython4.1.2--An enhanced InteractivePython.In[1]: values =[str(num)for num in range(int(1e3))]In[2]:%%timeit
...:''.join(values)...:100000 loops, best of 3:7.37µs per loop
In[3]:%%timeit
...: result =''...:for value in values:...: result += value
...:10000 loops, best of 3:82.8µs per loop
In[4]:import io
In[5]:%%timeit
...: writer = io.StringIO()...:for value in values:...: writer.write(value)...: writer.getvalue()...:10000 loops, best of 3:81.8µs per loop
Да, reprвызов доминирует во время выполнения, но нет необходимости делать ошибку личной.
Alex Reinking
3
@AlexReinking извините, ничего личного не имел в виду. Я не уверен, что заставило вас думать, что это личное. Но если это было использование их имен, я использовал их только для ссылки на ответы пользователя (соответствует именам пользователей, не уверен, есть ли лучший способ).
GrantJ
1
хороший пример синхронизации, который разделяет операции инициализации и конкатенации данных
aiodintsov
19
У Python есть несколько вещей, которые служат для аналогичных целей:
Один из распространенных способов создания больших строк из частей - это вырастить список строк и присоединиться к нему, когда вы закончите. Это часто используемая идиома Python.
Чтобы построить строки, включающие данные с форматированием, вы должны выполнить форматирование отдельно.
Для вставки и удаления на уровне символа вы должны вести список строк длиной один. (Чтобы сделать это из строки, вы должны вызвать list(your_string). Вы также можете использовать UserString.MutableStringдля этого.
(c)StringIO.StringIO полезен для вещей, которые в противном случае занимали бы файл, но в меньшей степени для общего построения строк.
Нет явного аналога - я думаю, вы должны использовать конкатенации строк (вероятно, оптимизированные, как было сказано ранее) или сторонний класс (я сомневаюсь, что они намного эффективнее - списки в python динамически типизированы, поэтому нет быстрой работы char [] для буфера, как я предполагаю). Классы, подобные Stringbuilder, не являются преждевременной оптимизацией из-за врожденной особенности строк во многих языках (неизменяемость), что позволяет выполнять множество оптимизаций (например, ссылаться на один и тот же буфер для срезов / подстрок). Классы Stringbuilder / stringbuffer / stringstream работают намного быстрее, чем объединение строк (создание множества небольших временных объектов, которые по-прежнему нуждаются в выделении памяти и сборке мусора) и даже инструменты форматирования строк, подобные printf, не требующие интерпретации накладных расходов шаблона форматирования, что довольно затратно для много форматных звонков.
Если вы здесь ищете метод быстрой конкатенации строк в Python, вам не нужен специальный класс StringBuilder. Простая конкатенация работает без потери производительности, наблюдаемой в C #.
Ответы:
Однозначной корреляции нет. По-настоящему хорошую статью см. В разделе Эффективная конкатенация строк в Python :
источник
Я использовал код Оливера Кроу (ссылка предоставлена Эндрю Хейром) и немного адаптировал его для адаптации Python 2.7.3. (с использованием пакета timeit). Я работал на своем персональном компьютере, Lenovo T61, 6 ГБ ОЗУ, Debian GNU / Linux 6.0.6 (сжатие).
Вот результат для 10000 итераций:
и для 5 000 000 итераций (метод 2 был проигнорирован, потому что он работал слишком медленно, как всегда):
Совершенно очевидно, что разработчики Python проделали отличную работу по оптимизации конкатенации строк, и, как сказал Хоар, «преждевременная оптимизация - это корень всех зол» :-)
источник
Полагаться на оптимизацию компилятора хрупко. Контрольным показателям, указанным в принятом ответе, и цифрам, приведенным Антуаном-Траном, нельзя доверять. Эндрю Хэйр совершает ошибку, включая обращение к
repr
своим методам. Это в равной степени замедляет работу всех методов, но скрывает реальный ущерб при построении строки.Используйте
join
. Это очень быстро и надежно.источник
repr
вызов доминирует во время выполнения, но нет необходимости делать ошибку личной.У Python есть несколько вещей, которые служат для аналогичных целей:
list(your_string)
. Вы также можете использоватьUserString.MutableString
для этого.(c)StringIO.StringIO
полезен для вещей, которые в противном случае занимали бы файл, но в меньшей степени для общего построения строк.источник
Используя метод 5, описанный выше (Псевдо-файл), мы можем получить очень хорошую производительность и гибкость.
теперь использую это
источник
вы можете попробовать StringIO или cStringIO
источник
Нет явного аналога - я думаю, вы должны использовать конкатенации строк (вероятно, оптимизированные, как было сказано ранее) или сторонний класс (я сомневаюсь, что они намного эффективнее - списки в python динамически типизированы, поэтому нет быстрой работы char [] для буфера, как я предполагаю). Классы, подобные Stringbuilder, не являются преждевременной оптимизацией из-за врожденной особенности строк во многих языках (неизменяемость), что позволяет выполнять множество оптимизаций (например, ссылаться на один и тот же буфер для срезов / подстрок). Классы Stringbuilder / stringbuffer / stringstream работают намного быстрее, чем объединение строк (создание множества небольших временных объектов, которые по-прежнему нуждаются в выделении памяти и сборке мусора) и даже инструменты форматирования строк, подобные printf, не требующие интерпретации накладных расходов шаблона форматирования, что довольно затратно для много форматных звонков.
источник
Если вы здесь ищете метод быстрой конкатенации строк в Python, вам не нужен специальный класс StringBuilder. Простая конкатенация работает без потери производительности, наблюдаемой в C #.
См . Ответ Антуана-транна о результатах работы
источник