Pythonのリスト操作時の注意 (リファレンスの共有)
[履歴] [最終更新] (2013/07/21 23:26:37)

概要

Rubyなどと同様に、代入ステートメントではオブジェクトは生成されずにリファレンスがコピーされるだけです。そのため、ある変数に格納されているリファレンスを用いてオブジェクトの値を変更すると、別の変数に格納されているリファレンスから参照したときにも値が変更されていることになります。

sample.py

L1 = [1,2]
L2 = L1

L1 += [3,4]
print L2

出力例

$ python sample.py 
[1, 2, 3, 4]

これを回避するためには、新たなオブジェクトが生成されるように工夫する必要があります。

sample.py

L1 = [1,2]
L2 = L1

L1 = L1 + [3,4]  # 新たなオブジェクトを生成し、そのリファレンスを代入
print L2

出力例

$ python sample.py 
[1, 2]

関数の引数で生じる同様の現象

下記の例では、リストListの内容は上書きされ、valの内容は保持されたままです。
この挙動はC言語などの配列 (ポインタ相当)、あるいはPerlの無名配列と同じです。

sample.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

def func(val,L):
    L[0] = val
    val = 1024

val = 512
List = [128,256];
func(val,List)

print val, List

出力例

$ python sample.py 
512 [512, 256]

スライシングを使用してコピーを生成するなどして回避できます。

sample.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

def func(val,L):
    L[0] = val
    val = 1024

val = 512
List = [128,256];
func(val,List[:])

print val, List

出力例

$ python sample.py 
512 [128, 256]
関連ページ
    概要 Python で数学的なことを試すときに利用される Matplotlib/SciPy/pandas/NumPy についてサンプルコードを記載します。 Matplotlib SciPy pandas NumPy チュートリアル Installing packages Quickstart tutorial