爬虫類嫌いのPython日記

爬虫類が大の苦手の筆者が、Pythonに挑戦。他にも、RubyやObjective-C、Google Appengine、Herokuなど色々とチャレンジしています。

Pythonの変数における共有リファレンス

O'REILLY社の「初めてのPython」6章より。

変数について

Pythonでは、C言語Javaなどスタティックな型付けのコンパイラ言語とは違い、変数の作成時に型宣言をする必要がありません。これは、Pythonでは型情報はオブジェクトが持ち、変数はオブジェクトへのリファレンスを持つからです。

どの変数からも参照されなくなったオブジェクトは、自動的にガーベージコレクションされ消滅します。

共有リファレンス

>>> a = 3     # 変数aは数値オブジェクト「3」へのリファレンスを持つ
>>> b = a     # 変数bは、変数aと同じオブジェクトへのリファレンスを持つ
>>> a = a + 2 # 変数aは、新たに作成された数値オブジェクト「a + 2」へのリファレンスを持つ

普通であれば、3行目のa = a + 2の部分で同じリファレンスを持つ変数bにも影響が出そうですが、整数は不変性を持つオブジェクトなので変更される事はありません。
可変性のオブジェクトであれば、変更されてしまうので注意が必要です。

>>> L1 = [2, 3, 4]  # 可変性のオブジェクトを生成
>>> L2 = L1         # L1とL2で、同じオブジェクトを共有
>>> L1[0] = 100     # 要素を上書きする
>>> L1              # L1に対応するリストには変更が加えられている          
[100, 3, 4]
>>> L2              # L2にも変更が影響
[100, 3, 4]

オブジェクトの比較には「同等」と「同一」があります。
「同等」は、オブジェクトの値が同じかの比較です。
「同一」は、オブジェクトが全く同じかの比較です。

>>> L = [1, 2, 3]
>>> M = L
>>> L == M        # 両者が「同等」であるかの比較
True
>>> L is M        # 両者が「同一」であるかの比較
True
>>> L = [1, 2, 3]
>>> M = [1, 2, 3] # LとMの対応するオブジェクトは別物
>>> L == M        # 両者の値は同じ
True
>>> L is M        # 「同等」だが「同一」ではない
False

しかし、小さい数値に対して行うと結果が異なるので要注意です。

>>> A = 25
>>> B = 25     # 本来、2つの数値オブジェクトは「同一」ではないはず
>>> A == B
True
>>> A is B     # 小さな数値オブジェクトはキャッシュされるので「同一」となる
True