まとめ
- 変数とはオブジェクトを参照するための名前で、変数の参照するオブジェクトはid(hoge)で確認できる
- y = x の意味は、代入先の変数yが参照するオブジェクトを、代入元の変数xが参照するオブジェクトにする、ということ
- xがintであろうとlistであろうとtupleであろうと全ての変数で共通の動作である
- 参照渡しとは変数そのものの参照を渡すことなので、いわゆる参照渡しはできない
- リストの要素を代入した時も同様であるが、リスト自体の参照先は変更されないため、一見参照渡しのような挙動にみえる
代入するときの挙動確認
intの変数を代入する
- 変数aの参照先が代入によって変数bの参照先に変わる
a = 1
b = 2
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
a = b # aのidはbのidに置き換わる
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
結果
a: 1 b: 2
id_a: 93893417024192 id_b: 93893417024224
a: 2 b: 2
id_a: 93893417024224 id_b: 93893417024224
bに新たな変数3を代入する
- bに3を代入すると、bは3という新たなオブジェクトを参照する
- このときaは元の参照先のままなので、変更の影響は受けない
b = 3 # bのidは3のidに置き換わる, aのidはそのまま
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
結果
a: 2 b: 3
id_a: 93893417024224 id_b: 93893417024256
変数がlistの場合
- intの場合と同じ
a = [1,1]
b = [2,2]
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
a = b # aのidはbのidに置き換わる
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
b = [3,3] # bのidは3のidに置き換わる, aのidはそのまま
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
結果
a: [1, 1] b: [2, 2]
id_a: 140361960710984 id_b: 140361960208392
a: [2, 2] b: [2, 2]
id_a: 140361960208392 id_b: 140361960208392
a: [2, 2] b: [3, 3]
id_a: 140361960208392 id_b: 140361960256584
listの要素への代入
- リストの要素に対して代入をするときは、リストの要素の参照先は変わるが、リストそのものの参照先は変わらない
- aとbの参照先は同じオブジェクトのままなので、aはbの変更の影響を受ける
- リスト要素の参照先が変わっていることから、参照渡しをしている訳ではないことが分かる
a = [1,1]
b = [2,2]
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
print("id_a[0]:", id(a[0]), "id_b[0]:", id(b[0]))
a = b # aのidはbのidに置き換わる
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
print("id_a[0]:", id(a[0]), "id_b[0]:", id(b[0]))
b[0] = 3 # b[0]のidは3のidに置き換わると同時にa[0]のidも3のidに置き換わる, aとbのidは元のまま
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
print("id_a[0]:", id(a[0]), "id_b[0]:", id(b[0]))
結果
a: [1, 1] b: [2, 2]
id_a: 140361961620360 id_b: 140361958272904
id_a[0]: 93893417024192 id_b[0]: 93893417024224
a: [2, 2] b: [2, 2]
id_a: 140361958272904 id_b: 140361958272904
id_a[0]: 93893417024224 id_b[0]: 93893417024224
a: [3, 2] b: [3, 2]
id_a: 140361958272904 id_b: 140361958272904
id_a[0]: 93893417024256 id_b[0]: 93893417024256
dict型の要素の代入
dict内部に直接代入する場合、dictのidは変わらず、代入したdict要素のidが置き換わる。
このとき、dictのidを共有している変数があれば、dictのidが不変なため、dict要素が変更されている。
a = {0:1}
b = {0:2}
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
print("id_a[0]:", id(a[0]), "id_b[0]:", id(b[0]))
a = b # aのidはbのidに置き換わる
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
print("id_a[0]:", id(a[0]), "id_b[0]:", id(b[0]))
b[0] = 3 # b[0]のidは3のidに置き換わると同時にa[0]のidも3のidに置き換わる, aとbのidは元のまま
print("a:",a,"b:",b)
print("id_a:", id(a), "id_b:", id(b))
print("id_a[0]:", id(a[0]), "id_b[0]:", id(b[0]))
結果
a: {0: 1} b: {0: 2}
id_a: 140362018772456 id_b: 140361986516168
id_a[0]: 93893417024192 id_b[0]: 93893417024224
a: {0: 2} b: {0: 2}
id_a: 140361986516168 id_b: 140361986516168
id_a[0]: 93893417024224 id_b[0]: 93893417024224
a: {0: 3} b: {0: 3}
id_a: 140361986516168 id_b: 140361986516168
id_a[0]: 93893417024256 id_b[0]: 93893417024256
参考資料:
プログラミング FAQ — Python 3.8.1rc1 ドキュメント
C#でわかる値渡し、参照渡し - Qiita
なぜ、Java、JavaScript、Python、Ruby等で「参照渡し」の言葉を使うべきではないのか? - Qiita
もう参照渡しとは言わせない - Qiita