Python
 Computer >> コンピューター >  >> プログラミング >> Python

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()関数を利用する方法もあります。

  1. Tkinterでリストボックス(Listbox)の項目テキストを変更する方法

    アプリケーション内に項目の一覧を表示したい場合、Tkinterが提供するListboxウィジェットが便利です。Listboxを使うと、複数の項目を縦方向に並べたリストを簡単に作成できます。ここで問題になるのが「すでに表示されている項目のテキストを変更したい」というケースです。Listboxには項目のテキストを直接書き換えるメソッドがないため、以下の手順で実現します。listbox.curselection() を使って、現在選択されている項目のインデックスを取得するlistbox.delete() で該当する項目を削除するlistbox.insert() で新しいテキストの項目を挿入するサンプ

  2. 【初心者向け】Pythonで文字列の長さを取得する方法をわかりやすく解説

    Pythonで文字列の長さを取得する基本:len()関数Pythonには、文字列やリスト、タプルといった複合オブジェクトの長さ(要素数)を取得できる組み込み関数 len() が用意されています。文字列の長さを知りたい場合は、対象の文字列をそのまま len() の引数として渡すだけでOKです。print(len(abcdefghijklmnopqrstuvwxyz))出力結果:26変数に格納した文字列の長さを取得する実際の開発では、変数に代入した文字列の長さを調べる場面が多いでしょう。次のように、変数を len() に渡すだけで簡単に取得できます。text = Hello, Python! pr