Pythonでの値渡しと参照渡し
多くの言語にはデータの「値渡し」「参照渡し」などと言われる仕組みがそなわっていますが、Pythonにも同じ仕組みがあります。
値渡しとは関数の引数として変数を指定したとき、関数内で引数を変更しても、もとの変数は変更されないことを言います。
def addOne(x): x = x + 1 print x y = 1 addOne(y) print y
結果
2 1
値渡しの場合は、このように関数内で引数に1加算しても、関数外の変数には影響しません。
一方でリストなどを引数とした場合には参照渡しとなり、その変数の中身を書きかえることができます。
def addOneList(l): l[0] = l[0] + 1 print l m = [0,1,2,3] addOneList(m) print m
結果
[1, 1, 2, 3] [1, 1, 2, 3]
値渡しになるか、参照渡しになるかはその変数によって変わります。値渡し、つまり変更ができない変数を「immutable」、参照渡し、つまり変更可能な変数を「mutable」と呼びます。
大まかにはPythonでは数値や文字列などはimmutable、リストや辞書型、クラスのインスタンスなどはmutableです。
これは他の言語とほぼ同様ですが、他の言語では文字列が参照渡しで行われることも多い一方で、Pythonでは値渡しという所は覚えておく必要があります。
値渡しと参照渡しがある理由
なぜこのような仕組みがあるか理解するには、値渡し、参照渡しそれぞれの利点、難点を知る必要があります。
値渡しは引数で与えられた変数の中身をコピーし、新しい変数に入れかえています。そのため、関数内の変数がプログラムの他の部分と独立しており(スコープが異なり)、関数外に影響を与えないことから、プログラムの管理が楽になります。しかし、一方で変数のコピーは負荷の高い処理のため、特に大きなデータの場合には処理が遅くなります。
参照渡しは引数のデータをコピーせずにそのまま使い回すため、どれだけ大きなデータを引数としてもパフォーマンスにはほとんど影響しません。一方で個々の関数内でデータを書きかえられるため、プログラムのどこでデータが変更されたかを管理するのは難しくなります。実際、参照渡しの変数をうっかり書きかえてしまうことによるバグは、初心者がかならず経験するものの一つです。
このような利点、難点があり、それぞれの利点を有効に利用するため、多くのプログラム言語ではデータの小さい変数型は値渡し、データが大きくなる可能性のある変数型は参照渡しとする言語仕様が採用されています。
その意味では文字列型は参照渡しの方が良さそうですが、Pythonでは言語仕様を簡単にするためか、値渡しとなっています。大きな文字列をあつかうときには処理が遅くなりがちなので注意が必要です。
Pythonで大きな文字列を頻繁に編集する場合には、リストに変換することなどが常套手段とされています。
Page Info | |
---|---|
Page Name : | Python/値渡しと参照渡し |
Page aliases : | None |
Page owner : | njf |
Can Read | |
Groups : | All visitors |
Users : | All visitors |
Can Edit | |
Groups : | All visitors |
Users : | All visitors |