Pythonの文字列は不変(イミュータブル)!同じ文字列でもid()が変わる仕組みを解説
Pythonにおいて、文字列(str型)は不変(イミュータブル)なオブジェクトです。つまり、一度作成された文字列は後から変更できません。
また、Pythonでは同じ内容の文字列を作成して別々の変数に代入した場合、両方の変数が同じ文字列オブジェクト(同じメモリ領域)を参照するように最適化されることがあります。実際に確認してみましょう。
同じ文字列は同じid()を持つケース
>>> a = 'hi' >>> b = 'hi' >>> id(a) 43706848L >>> id(b) 43706848L
このように、変数aと変数bはまったく同じid(メモリアドレス)を持っています。このような文字列オブジェクトの再利用は、「インターン(interning)」と呼ばれる仕組みです。同一内容の文字列同士は同じidを共有することになります。
インターンは常に保証されているわけではない
ただし注意が必要なのは、Pythonがすべての文字列を必ずインターンするとは限らないという点です。具体的には、以下のような文字列はインターンの対象外となり、id()の値が再利用されません。
- コードオブジェクトの定数として扱われない文字列
- 英字・数字・アンダースコア以外の文字(記号など)を含む文字列
実際に、記号を含む文字列で試してみると挙動の違いがわかります。
特殊文字を含む文字列はid()が異なるケース
>>> a = 'weworks_45#@$' >>> b = 'weworks_45#@$' >>> id(a) 96226208L >>> id(b) 91720800L
この例では、まったく同じ内容の文字列を2つの異なる変数に代入していますが、それぞれのid()の値は異なる結果になっています。これは、文字列に「#」「@」「$」といった英数字・アンダースコア以外の文字が含まれているためです。このような文字列はインターンされず、代入のたびに新しい文字列オブジェクトが生成されます。
まとめ
Pythonの文字列は不変であり、単純な英数字のみの文字列はインターンによってidが共有されることがありますが、それは言語仕様として保証された動作ではありません。文字列の同一性を判定したい場合は、id()ではなく==演算子による値の比較を使うのが安全です。また、明示的にインターンを行いたい場合は、標準ライブラリのsys.intern()関数を利用する方法もあります。
-
Tkinterでリストボックス(Listbox)の項目テキストを変更する方法
アプリケーション内に項目の一覧を表示したい場合、Tkinterが提供するListboxウィジェットが便利です。Listboxを使うと、複数の項目を縦方向に並べたリストを簡単に作成できます。ここで問題になるのが「すでに表示されている項目のテキストを変更したい」というケースです。Listboxには項目のテキストを直接書き換えるメソッドがないため、以下の手順で実現します。listbox.curselection() を使って、現在選択されている項目のインデックスを取得するlistbox.delete() で該当する項目を削除するlistbox.insert() で新しいテキストの項目を挿入するサンプ
-
【初心者向け】Pythonで文字列の長さを取得する方法をわかりやすく解説
Pythonで文字列の長さを取得する基本:len()関数Pythonには、文字列やリスト、タプルといった複合オブジェクトの長さ(要素数)を取得できる組み込み関数 len() が用意されています。文字列の長さを知りたい場合は、対象の文字列をそのまま len() の引数として渡すだけでOKです。print(len(abcdefghijklmnopqrstuvwxyz))出力結果:26変数に格納した文字列の長さを取得する実際の開発では、変数に代入した文字列の長さを調べる場面が多いでしょう。次のように、変数を len() に渡すだけで簡単に取得できます。text = Hello, Python! pr