C#のStringBuilderのようなPython文字列クラス?


121

Python StringBuilderにC#のような文字列クラスはありますか?


6
これは、JavaのStringBufferに相当するPythonの複製です。注意:ここでの回答は時代遅れであり、実際、誤解を招くようになっています。最新のPythonバージョン(確かに2.7以上)に関連する回答については、他の質問を参照しください。
ジャン=フランソワ・コルベット

回答:


102

1対1の相関関係はありません。本当に良い記事については、Pythonでの効率的な文字列連結を参照してください。

Pythonプログラミング言語で長い文字列を作成すると、コードの実行が非常に遅くなることがあります。この記事では、さまざまな文字列連結方法の計算パフォーマンスを調査します。


27
この記事はPython 2.2に基づいて作成されていることに注意してください。最新バージョンのPythonではテストが多少異なる可能性があります(CPythonは通常、連結を最適化しますが、重要なコードでこれに依存する必要はありません)。リスト内包表記を使用するジェネレーター式は検討に値します。 。
マイクグラハム、

4
その記事で少なくともいくつかの実装(リンクの腐敗の問題を回避するため)のいくつかのハイライトを取り入れておくとよいでしょう。
jpmc26 2014

3
方法1:以下の@ Antoine-tranのテストによると、resultString + = appendStringが最も速い
Justas

5
あなたの引用は質問にまったく答えません。新しいガイドラインに準拠するため、回答自体に関連部分を含めてください。
モニカの訴訟に資金を提供

27

私はOliver Crow(Andrew Hareから提供されたリンク)のコードを使用し、Python 2.7.3を調整するために少し調整しました。(timeitパッケージを使用)。私は自分のパソコン、Lenovo T61、6GB RAM、Debian GNU / Linux 6.0.6(squeeze)で走りました。

10,000回の反復の結果は次のとおりです。

方法1:0.0538418292999秒
プロセスサイズ4800 kb
method2:0.22602891922秒
プロセスサイズ4960 kb
method3:0.0605459213257秒
プロセスサイズ4980 kb
method4:0.0544030666351秒
プロセスサイズ5536 kb
method5:0.0551080703735秒
プロセスサイズ5272 kb
method6:0.0542731285095秒
プロセスサイズ5512 kb

そして5,000,000回の繰り返し(方法2は、永久に実行されるのと同じくらいゆっくり実行されたため、無視されました):

method1:5.88603997231秒
プロセスサイズ37976 kb
method3:8.40748500824秒
プロセスサイズ38024 kb
method4:7.96380496025秒
プロセスサイズ321968 kb
method5:8.03666186333秒
プロセスサイズ71720 kb
method6:6.68192911148秒
プロセスサイズ38240 kb

Hoareが言ったように、Pythonの連中が文字列の連結を最適化するためにかなり素晴らしい仕事をしたことは明らかです。「早期の最適化はすべての悪の根源です」


2
:どうやらホーアは、受け付けませんhans.gerwitz.com/2004/08/12/...
PiminコンスタンチンKefaloukos

5
壊れやすく、インタプリタに依存する最適化を回避するのは時期尚早な最適化ではありません。PyPyに移植したい場合、または最適化のために多くの微妙な失敗事例の1つにヒットするリスクがある場合は、正しい方法で行ってください。
Veedrac 14年

1
方法1は、コンパイラーが最適化する方が簡単のようです。
mbomb007 2015

24

コンパイラの最適化に依存することは脆弱です。受け入れられた回答にリンクされているベンチマークと、Antoine-tranによって与えられた数値は信頼されるべきものではありません。Andrew Hareは、repr自分のメソッドに呼び出しを含めるという間違いを犯しています。これにより、すべてのメソッドが同等に遅くなりますが、文字列を作成する際の実際のペナルティがわかりにくくなります。

を使用しjoinます。非常に高速で堅牢です。

$ ipython3
Python 3.5.1 (default, Mar  2 2016, 03:38:02) 
IPython 4.1.2 -- An enhanced Interactive Python.

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には、同様の目的を満たすいくつかの機能があります。

  • ピースから大きな文字列を作成する一般的な方法の1つは、文字列のリストを拡張し、完了したらそれを結合することです。これは、頻繁に使用されるPythonイディオムです。
    • データにフォーマットを組み込んだ文字列を作成するには、フォーマットを個別に行います。
  • 文字レベルでの挿入と削除の場合、長さ1の文字列のリストを保持します。(これを文字列から作成するには、を呼び出しますlist(your_string)UserString.MutableStringこれにa を使用することもできます。
  • (c)StringIO.StringIO それ以外の場合はファイルを取得することには役立ちますが、一般的な文字列の構築にはそれほど役立ちません。

10

上記の方法5(疑似ファイル)を使用すると、非常に優れたパフォーマンスと柔軟性を得ることができます

from cStringIO import StringIO

class StringBuilder:
     _file_str = None

     def __init__(self):
         self._file_str = StringIO()

     def Append(self, str):
         self._file_str.write(str)

     def __str__(self):
         return self._file_str.getvalue()

今それを使っています

sb = StringBuilder()

sb.Append("Hello\n")
sb.Append("World")

print sb


-1

明確な類似物はありません-文字列の連結(前述のように最適化されている可能性が高い)またはサードパーティのクラス(それらの方がはるかに効率的であることを疑っています)-Pythonのリストは動的に型付けされているため、高速に機能しませんchar [](私が想定するバッファ)。Stringbuilderに似たクラスは、多くの言語の文字列に固有の機能(不変性)があるため、時期尚早の最適化ではありません。これにより、多くの最適化が可能になります(たとえば、スライス/サブストリングの同じバッファーの参照)。文字列ビルダー/文字列バッファー/文字列ストリームのようなクラスは、文字列の連結(割り当てとガベージコレクションを必要とする多くの小さな一時オブジェクトを生成する)や、文字列フォーマットのprintfのようなツールでさえ、かなり高速に動作します。多くのフォーマット呼び出し。


-4

ここでPythonの高速文字列連結メソッドを探している場合は、特別なStringBuilderクラスは必要ありません。単純な連結は、C#で見られるようなパフォーマンスの低下なしに、同様に機能します。

resultString = ""

resultString += "Append 1"
resultString += "Append 2"

パフォーマンスの結果については、Antoine-tranの回答を参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.