TomoProgの技術書

底辺プログラマーが達人プログラマーになるまで

Pythonでは関数の引数はすべて参照渡し?

皆さん
こんにちは、こんばんは
TomoProgです。

Pythonの関数の引数がすべて参照渡しということを知っていますか?
私はPythonを趣味で使い始めてそろそろ一年ぐらいだと思いますが、知らなかったです・・・。

ということで、
今日はPythonの関数の引数について少し調べてみたことをここに書いていこうと思います。

それでは頑張っていきましょう。

ほんとに参照渡しなの!?

関数の引数がすべて参照渡しらしいので、こんなコードを書いてみました。

#-*- coding:utf-8 -*-

def calc(y):
    y += 10

def main():
    x = 10
    calc(x)
    print(x)

if __name__ == "__main__":
    main()

すべて参照渡しならば結果は20になるはずだ!!

実行結果:
10

あれ?
参照渡しなのに20になっていないんですけど、どうゆうことなんでしょう・・・。

変数の識別値を調べてみる

Pythonには組み込み関数としてid()という関数が準備されています。

id(object)
オブジェクトの “識別値” を返します。この値は整数で、このオブジェクトの有効期間中は一意かつ定数であることが保証されています。有効期間が重ならない 2 つのオブジェクトは同じ id() 値を持つかもしれません。
引用元:2. 組み込み関数 — Python 3.4.3 ドキュメント

この組み込み関数を使用して先ほどのプログラムの変数の識別値を調べてみます。

#-*- coding:utf-8 -*-

def calc(y):
    print("id(y):" + str(id(y)))
    y += 10

def main():
    x = 10
    print("id(x):" + str(id(x)))
    calc(x)
    print(x)

if __name__ == "__main__":
    main()
実行結果:
id(x):10106112
id(y):10106112
10

確かに識別値は一緒なので、参照渡しであることは間違いないみたいです。
参照渡しなのになぜ値が変わらないのかgoogle先生に聞いてみることにします。

ミュータブルとイミュータブル

先生が教えてくれたのは以下のサイトでした。
rcmdnk.github.io

なるほど。
Pythonで使用できるオブジェクトにはミュータブル(変更可能)とイミュータブル(変更不可)のオブジェクトがあるみたいです。

# ミュータブルオブジェクト
list, set, dict など

# イミュータブルオブジェクト
int, float, str, tuple など

先ほど私が作ったプログラムの引数はintでイミュータブルなので変わらなかったようです。

ミュータブルなオブジェクトを引数にしてみる

ミュータブルオブジェクトなら値が書き変わるのか見てみます。
今回はリスト型で試してみました。

#-*- coding:utf-8 -*-

def func(dist):
    dist[0] = 2
    dist[1] = "apple"
    dist[2] = False

def main():
    src = [1, "banana", True] 
    print(src)

    func(src)
    print(src)

if __name__ == "__main__":
    main()
実行結果:
[1, 'banana', True]
[2, 'apple', False]

おぉ!!
確かにミュータブルオブジェクトであれば値が書き変わりました!!

まとめ

  • Pythonでは関数の引数はすべて参照渡しである。
  • 参照渡しでも書き換え可能なオブジェクトと書き換え不可能なオブジェクトが存在する。

今日はPythonの関数の引数について調べてみました。
1年使っても知らないことは多いものです。
それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub

Twitter
TomoProg (@tomoprog_xxx) | Twitter