#TL;DR
代入をするときポインタが渡される
constな値を代入した際にもその値のポインタが渡される
#Pythonでもある意味厄介なポインタ
C言語にもあるポインタの概念、こいつの仕様を理解しようと色々悪戦苦闘したのはなつかしいです(今でも理解できていない節がありますが)。その後Pythonでもポインタを使いたいと思い調べたら言語特有の省略主義的なものゆえか頭が完全にバグったのでまとめておきたいと思います。
(上記の通りポインタに対して完全な理解をしたわけではないので終始誤っていることを記述する可能性がありますが、ご了承ください。また以下のコードはすべてインタプリンタ上で動かしています)
#実行環境
python: Python 3.9.0
OS: Windows 10
#変数同士の代入
a=3
id(a) #1392940902768
b=9
id(b) #1392940902960
b=a
id(b) #1392940902768
id関数は引数のアドレスを返してくれます。上記のような単純な代入ではそこいらでも言われている通りちゃんとポインタ渡しになっています。
#値の代入
a=7
print(b) #9
id(a) #1392940902896
おかしくなっていくのはその後です。変数a,bは同じアドレスを共有しているので当然aに値を代入されれば同じようにしてbにも反映されるはずです。
ですが実際はそうはならず、さらにaのアドレスが変わってしまいました。C言語で似たようなことをすればそうはならないので混乱してしまいました。ただその後にふと確かめてみたことがあります。
#値のアドレス
id(7) #1392940902896
どうやら値自身にもアドレスが設定されているようです、constな変数ということでしょうか。
このことからpythonにはそもそも値渡しが存在しない、もしくは明記しないといけないのではないか?という可能性に至りました。
for i in range(20):
print(i,end=":")
print(id(i)-id(0))
0:0
1:32
2:64
3:96
4:128
5:160
6:192
7:224
8:256
9:288
10:320
11:352
12:384
13:416
14:448
15:480
16:512
17:544
18:576
19:608
値にはそれぞれアドレスが設定されており、一定の周期性を持つことがわかります。
よって前処理の段階であらかじめアドレスが設定されていることがわかります。
#listで回避してみる
a=[1,2,3]
id(a) #2960827260992
b=a
id(b) #2960827260992
a[0]=9
b #[9,2,3]
id(a) #2960827260992
このようにすればC言語みたいなポインタの使い方ができます。(任意のアドレス上にあるオブジェクトに格納されているオブジェクトのアドレスを変更しているということになるのでしょうか)
ただlistを前提とした運用ならともかく、上記のようにintで収まる範囲ならかなり違和感を覚えます。(もっといい書き方があると思いたい)
#値渡しをしてみる
import copy
a=3
id(a) #1392940902768
b=copy.deepcopy(a)
id(a) #1392940902768
id(b) #1392940902768
だめでした。(一つの変数が二つのアドレスを持つことになるので当然といえば当然ですが)
#toDO
・pythonリファレンスを確認する
確認しました。その結果上記のことは実装に依存する、というとんでもないことが書かれていたので後日追加の 検証をしてみたいと思います。探してくれた友人に感謝を。