Pythonの引数は全て参照渡しの件について

大学の研究室でPythonを教えていて,「Pythonにおいて,関数の引数は全て参照渡しなのだ!」みたいなことを言いつつ,

>>> def change(val):
...     val = 10
...     
... 
>>> a = 100
>>> change(a)  #aは10になるはず...
>>> a
100

あれれ?
だった件.

それでもPythonの引数は参照渡し

改めて調べてみたが,やはり参照渡しでした.
上記の例だと,aにはメモリ上の100という数値を挿している参照が入ります.
次に,change(a)が呼ばれると,change関数のval変数には,aに入っている参照がコピーされます.
ここで勘違いしてしまったのは,次のval=100という式の意味でした.
この式の意味は,メモリに10という数値作って,そこを挿している参照をvalに入れろ,という意味です.
そして,関数のスコープから抜けるとvalは廃棄対象になるのだと思います.

不変性オブジェクトと可変性オブジェクト

では,参照渡しのようにするにはどうすれば良いのか.
実は,基本的には整数や文字列のような不変性オブジェクトは関数内で上書きすることは出来ないっぽい.
そもそも,関数の中で引数で渡した変数の中身を変えることは余りよいこととされていない.
副作用とも呼ばれたりする.
関数には値を渡して,値を返すのが基本とされる.
では全く出来ないかというとそうでもない.
可変性オブジェクトと呼ばれるオブジェクトがある.
たとえば,リストやディクショナリがそうだ.

>>> a = [1,2,3,4,5]
>>> a.append(6)
>>> a
[1, 2, 3, 4, 5, 6]

これは,aが指し示しているリストオブジェクト自体を変更,上書きしている.
新しいリストを作って参照を入れ替えているのではない.
この手の型の変数であれば,関数内で値の上書き変更が出来る.

>>> a
[1, 2, 3, 4, 5, 6]
>>> def change(val):
...     val.append(100)
...     
... 
>>> change(a)
>>> a
[1, 2, 3, 4, 5, 6, 100]

とにかく,参照渡しが原則,というのは間違っていなかったみたいでした.