今回は変数が何を指しているかというところを深く見るための実験です。pythonのバージョンは3.4.3です。
別の変数からオブジェクトを変更する
変数の中身を別の変数に代入しても、同じオブジェクトを指しています。これをオブジェクトidを比較して確認します。
mylist = [[0, "mike"], [1, "jane"]]
person1 = mylist[0]
print("mylist = %s" % mylist)
print("person1 = %s" % person1)
# =>
# mylist = [[0, 'mike'], [1, 'jane']]
# person1 = [0, 'mike']
# 2つの変数が同じオブジェクトを指していることを確認
print("mylist[0] id = %s" % id(mylist[0]))
print("person1 id = %s" % id(person1))
print(id(mylist[0]) == id(person1))
# => True
# 後に確認するために現在のオブジェクトidを保存
person1_id = id(person1)
別変数を通して配列の要素を変更してみます。添字を指定した時だけ
# personがmylist[0]のエイリアスになっていることを確認
person1[0] = 100
print("mylist = %s" % mylist)
print("person1 = %s" % person1)
# =>
# mylist = [[100, 'mike'], [1, 'jane']]
# person1 = [100, 'mike']
要素の変更に成功しました。しかし、添字を使わない場合は要素の変更ができずに、新しいオブジェクトが代入されてしまっています。
# pesron1を通して、mylist[1]の配列の変更を試みる
person1 = [5, "michel"]
print("mylist = %s" % mylist)
print("person1 = %s" % person1)
# =>
# mylist = [[100, 'mike'], [1, 'jane']]
# person1 = [5, 'michel']
person1 = 5
print("mylist = %s" % mylist)
print("person1 = %s" % person1)
# =>
# mylist = [[100, 'mike'], [1, 'jane']]
# person1 = 5
前の配列の要素が入っていた時のオブジェクトidと比較すると、確かにオブジェクトが変わってしまっていることが確認できます。
# オブジェクトを変更する前のidと比較
print(person1_id == id(person1))
# => False
変数が何を指しているのか
上記の現象を図解してみます。まずは添え字を使った場合です。添え字を使った場合は配列(今回はlist)を指しているのではなく、その要素を指していることに注意しましょう。配列の要素の参照(矢印)を変更しただけなので、配列を参照していた変数は変わらず配列を参照したままです。
次は添え字を使わなかった場合です。先ほどの実験で、この場合は別の変数から値を変更した場合に、もとの変数に影響がでなかったですよね。これは配列への参照を新しいオブジェクトへの参照に変更したのが原因です。