Q1:
動かしてみれば一発でわかる通り、関数の中での代入はローカル変数に代入され、外のx
には影響を及ぼしません。
ただし、ローカル変数x
を作らない限りは外のスコープ(定義元)から探してきます。
stackだし、基本的には常識的な動作でしょう(それでもたまに変に見えるときがありますが)。
Q2:
Obj1
,Obj2
が変数名ならば、代入はアドレスの代入です。
python
1>>> a = 1
2>>> b = 2
3>>> id(a)
49169088
5>>> id(b)
69169120
7>>> a = b
8>>> id(a)
99169120
10>>> id(b)
119169120
id(≒アドレス)が9169088のオブジェクト(1
)はこの場合、参照されなくなってGCが回収していく、というのが原則。ただし、上に続けてid(1)
と打つと、
python
1>>> id(1)
29169088
このような結果が得られると思います。こういう、しょっちゅう使いそうな小さい数字のオブジェクトを、必要になるたびに作り直していたら不経済なことこの上ないので、内部でキャッシュしている訳です。もちろんすべての数で同じ挙動にはなりません。ある程度大きい数はキャッシュされないようです。
python
1>>> a = 1
2>>> id(a)
39169088
4>>> del a
5>>> a = 1
6>>> id(a)
79169088
8>>> a = 1024
9>>> id(a)
10140587587642416
11>>> del a
12>>> a = 1024
13>>> id(a)
14140587610978288
ちょっと話が脱線しましたが、pythonの場合は代入は常に参照を張るだけと思ってまず間違いありません。
例外っぽいのは、
+=
などは可能であればin-placeで処理されます。つまり、元のオブジェクトが変わります。
list[i] =
等、添字表記やスライスに代入するもの
これはオブジェクトの__setitem__
メソッドで処理されます。だから、変な動作にしようと思えばいくらでも出来ます(普通はそんなことはしないで、常識的な動作になる訳だが)。