HOWTO · Python
Python で同等の StringBuilder
このチュートリアルは、Python の StringBuilder クラスに相当するものを示しています
このページの内容
Pythonには、他の言語にあるような組み込みのStringBuilderクラスはありません。代わりに、各要素がどのように得られるかに応じて文字列の組み立て方を選びます。文字列の反復可能オブジェクトにはstr.join()、少数の固定された要素には+、要素を順次書き込む場合にはio.StringIOを使います。f文字列は値を文字列に書式化するためのもので、任意の要素を並べて蓄積する汎用バッファではありません。
Pythonの文字列は不変です。内容を変える操作をすると、元の文字列をその場で変更するのではなく、新しい文字列値が生成されます。この性質から、結果を繰り返し大きくしていく方法が一般的には適さない場合があると分かりますが、+を使うたびに遅くなるという意味ではありません。要素数が少なく固定された式なら、連結は分かりやすく実用的です。
PythonにおけるStringBuilder相当の意味
プログラムで多くの要素からテキストを組み立てる場合、StringBuilderのようなAPIが役立ちます。Pythonには同じ目的に使える標準の方法がありますが、あらゆる用途に置き換えられる単一のクラスはありません。どの方法が最も読みやすいかは、入力の形とテキストの生成方法によって決まります。
str.join()で要素から文字列を作る
文字列の反復可能オブジェクトがすでにある場合は、区切り文字列にjoin()を使います。区切り文字は隣り合う要素の間に入り、先頭や末尾には付きません。たとえば、" / ".join(parts)は、値の間に前後の空白を含むスラッシュを挟んで連結します。各要素は文字列でなければなりません。文字列以外の値は連結前に変換するか、より大きなメッセージの一部として値を表示する場合は書式化を使います。
次の例を実行します。
このセクションのコードと表示されるラベルや出力は英語のままです。
parts = ["docs", "python", "strings"]
path = " / ".join(parts)
print(path)
docs / python / strings
既知の文字列の集まりを連結する場合、join()は便利な基本の選択肢です。区切り文字が明示され、結果を繰り返し大きくするループを書く必要もありません。常に最速であることを保証するものではないため、入力の形と目的に合っているかを基準に選びます。
+による連結が適切な場合
要素数が少なく固定されている場合は、+を使います。たとえば、挨拶に名前を加える場合や、ラベルに句読点を付ける場合です。式に要素がそのまま示されるので、連結のためだけにコレクションを作るより簡潔なこともよくあります。
ループを何度も回して要素を生成する場合、result = result + pieceを繰り返すと、次々に文字列値が作られ、不要な処理が生じることがあります。文字列の要素を集めて最後に一度だけ連結するか、各要素を生成しながら書き込むのが自然な場合はStringIOを使います。実際の性能はプログラムやPythonの実装によって異なるため、根拠のない一律の順位で選ばないようにします。
io.StringIOで順次書き込む
テキストを段階的に生成する場合、io.StringIOを使うと、write()メソッドを備えたメモリ上のテキストストリームを利用できます。ioからインポートし、文字列の要素を書き込んでから、getvalue()を呼び出して蓄積した文字列を取得します。異なる分岐や処理段階から要素が届くような、出力を中心とするコードを読みやすくできます。write()に渡す各引数は文字列でなければなりません。ストリームの生存期間を明確にするのに役立つ場合はコンテキストマネージャーを使い、完成した値を後で使うなら、そのスコープを抜ける前にgetvalue()を呼び出します。
このセクションのコードと表示されるラベルや出力は英語のままです。
from io import StringIO
with StringIO() as output:
output.write("Hello")
output.write(", ")
output.write("Python")
message = output.getvalue()
print(message)
Hello, Python
通常、独自のラッパーは必要ありません。アプリケーションで必要な場合は、複数のビルダー間で状態を共有しないよう、バッファを各インスタンスに持たせます。
f文字列で値を書式化する
値を文字列に書式化する場合は、f文字列を使います。波括弧内の式が評価され、表示用に変換されるため、短いメッセージを読みやすく書けます。
このセクションのコードと表示されるラベルや出力は英語のままです。
name = "Ada"
count = 3
message = f"{name} has {count} tasks."
print(message)
f文字列は値の埋め込みに使うもので、任意の要素の集まりを順次追加するためのものではありません。値がコレクションなら、文字列の要素を用意してjoin()を使います。テキストを段階的に書き込む場合は、StringIOを検討します。このように使い分けると、書式化と蓄積を区別できます。
目的に合った文字列の組み立て方を選ぶ
- 文字列の反復可能オブジェクトがあり、要素の間に区切り文字を入れたい場合は
str.join()を使います。 - 要素数が少なく固定され、各要素が明確に分かる場合は
+を使います。 - ストリームのようなインターフェースを通じてテキストを順次書き込む場合は
io.StringIOを使います。 - メッセージなどの書式化された文字列に少数の値を埋め込む場合は、f文字列を使います。
どの状況にも当てはまる、PythonのStringBuilderの単一の置き換え方法はありません。要素の渡され方に合った方法を選び、選んだ操作が文字列を必要とする場合は値を文字列に変換します。これらの方法を使えば、どれかが常に最速だという一律の主張に頼らず、実用的にテキストを組み立てられます。