Programmingバックエンド開発者

Pythonは文字列(str)の処理をどのように実装していますか?Pythonにおける文字列の不変性は、例えばリストとはどのように異なりますか?大規模なデータを操作する際の文字列操作の注意点は何ですか?

Hintsage AIアシスタントで面接を突破

回答

Pythonでは、文字列(str)は不変オブジェクトであり、一度作成するとその内容を変更することはできません。文字列を変更する操作(例えば、連結や文字の置換)は、新しい文字列オブジェクトを作成します。これにより、安全性と予測可能性が確保され、他のコードの部分で誰かが暗黙的に文字列を変更することを心配する必要がありません。

s = 'Hello' s2 = s.replace('H', 'J') # sは'Hello'のままで、s2は'Jello'になる

文字列とは異なり、Pythonのリストは可変オブジェクトです。インデックスやメソッドを介してその内容をインプレースで変更できるため、同じリストが異なる場所で使用されると、暗黙的な影響を及ぼすことがあります。

性能の観点から:大きな文字列を頻繁に変更する必要がある場合(例えばループ内で)、不変性のメカニズムが過剰なメモリの割り当てやコードの遅延を引き起こすことがあります。このような場合は、文字列の断片を蓄積するためにリストを使用し、後で''.join()を介して結合することをお勧めします。

例:

# 悪い(大規模データに対して遅い): s = '' for word in words: s += word # 各ステップで新しい文字列が作成される # 良い: parts = [] for word in words: parts.append(word) s = ''.join(parts)

ひっかけ問題

質問: なぜ次のコード "s += 'abc'" が "s = s + 'abc'" よりも速いのですか?

回答: このような質問は、両方の操作が実際に文字列に対して同等であることを理解しているかどうかを確認するためにされます(s += 'abc' は新しいオブジェクトを作成し、s = s + 'abc' も同様)—Pythonの型の挙動はこのように設計されています。リストの場合は挙動が異なり、list += [...] はオブジェクトを変更し、list = list + [...] は新しいものを作成します。文字列の場合は常に新しい文字列になります。

s = 'hi' s += 'abc' # 新しいオブジェクト、元の文字列は変更されない def compare(s): a = s a += 'abc' # id(a) != id(s) <-- メモリ内の異なるオブジェクト

知識不足による実際のエラーの例


物語

大規模なログを処理するプロジェクトで、開発者がループ内で文字列を単純に連結する方法を使用しました。結果として、パフォーマンスが大幅に低下し、メモリ消費が急増しました。リストとjoin()を使用して最適化した結果、実行時間は20倍に減少しました。


物語

あるプロジェクトで、インデックスを使用して文字列内の文字を「修正」しようとしたプログラマーは、元の文字列が変更されると期待していました。TypeError: 'str' object does not support item assignmentというエラーが発生しました。数時間を費やした後、デバッガーはスライスを使用して新しい文字列を作成し、必要な文字を置き換えなければなりませんでした。


物語

関数に文字列を渡してそれを「補完」する際(例えば、リストの各要素に接尾辞を追加する場合)、ある開発者は文字列が「その場で」変更されると期待しました。結果として、関数はNoneを返し(returnがないため)、すべての文字列が元のまま残りました。