2009-08-27 6 views
4

C++では、void somefunction(int)が値を渡し、void somefunction(int&)は参照を渡します。 Javaでは、プリミティブは値で渡され、オブジェクトは参照渡しされます。どのようにしてこの決定を下すのですか?Pythonは、パラメータが参照か値かをPythonがどのように決定しますか?

編集:

def foo(num): 
    num *= 2 

a = 4 
foo(a) 

print(a) 

印刷 '4' の代わりに '8' の:すべては参照渡しされているので、なぜこれをしますか?

+1

受け入れられた回答は実際には間違っています。 by-valueとby-referenceとの違いについてのniceacctの答えを見てください。 –

+1

私はそれが間違っていることに同意しません。議論は用語についてであり、私たちがPythonがリファレンスとして渡すというより、参照値を渡すと言うことを望みます。私はその専門用語の違いを、教育的観点から見てもわかりません。 –

+0

これはこの質問と重複しています:http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference 悲しいことに、その質問については当初受け入れられた答えも間違っていました(今受け入れられた答えはかなり良いです)、ちょうどStefanosの答えのように。 – nikow

答えて

9

ここでは、用語の不一致があります。 Javaコミュニティでは、すべてが価値によって渡されていると言われています。参照は値渡しされます。 (このサイトでJavaを検索して、これを信じていないと参考にして渡してください)。 "オブジェクト"は言語の値ではありません。オブジェクトへの参照のみが存在します。

Javaでは、参照を渡すときに、呼び出し元のスコープ内の元の参照変数は、呼び出し元によって決して変更できない(つまり、別のオブジェクトを指すようにする)参照渡しで可能です。参照によって指し示されたオブジェクトだけが突然変異されるかもしれないが、それは無関係である。

Pythonの値は、Javaの参照とまったく同じ方法で動作します。同じ定義を使用すると、Pythonのすべてが参照であり、すべてが値渡しであると言います。もちろん、Pythonコミュニティの中には、別の定義を使用するものもあります。

用語の不一致が混乱の原因の大部分です。

あなたが持っているC++、PythonのコードはC++でのこのようなものに相当します言及ので:引数は、JavaやPythonでの参照に最も類似しているポインタであることを

void foo(const int *num) { 
    num = new int(*num * 2); 
} 

const int *a = new int(4); 
foo(a); 

print(a); 

注意。

1

すべては参照渡しです。すべてが目的でもあります。

+1

すべてが** an **オブジェクトです。 – voyager

+0

@voyager:ありがとうございました。 –

+2

実際には値渡しされます。つまり、参照は値渡しです。 –

11

参考までにすべてを渡します。数値を指定した場合でも、その値を含むテーブルに対する参照です。これは、静的言語と動的言語の違いです。型はコンテナではなく値で保持され、変数はすべての値が存在する「値空間」への参照に過ぎません。変更可能なすべてのオブジェクト(整数、浮動小数点数、文字列)に加えて、作成するすべての変更可能なオブジェクト(リスト、dicts、オブジェクト)を含むこの値空間を想定することができます。もちろん、それらの存在は、あなたがそれらを関与させるときにのみ具体化されます(つまり、あなたのプログラムで42という数字を使用しないなら、 "値の空間"の値42に割り当てられたスペースはありません)。

これは、参照している番号が不変オブジェクトであるためです。何があっても4は4です。

def foo(num): # here, num is referring to the immutable entity 4 
    num *= 2 # num now refers to the immutable entity 8 

a = 4  # a now is pointing to the immutable entity 4 
foo(a)  # a is still referring to the same entity 4 

print(a)  # prints what a refers to, still 4 

あなたの編集に対応して、この

def foo(l):  # here, l refers to the list it receives 
    l.append(5) # the list is appended with the number 5 

a = []  # a now is pointing to a specific mutable list 
foo(a)  # a is still referring to the same specific mutable list 

print(a)  # prints what a refers to, the specific mutable list which now contains [5] 
+0

あなたの答えをありがとう。私は 'String'がJavaで動作する方法と似ていると思います。 Pythonの不変オブジェクトのどこかにリストがありますか? –

+1

はlist、dict、そして基本的にはすべてが変更可能です。変更不可能な文字列、タプル、整数、浮動小数点数です。 –

+1

frozensetも不変です。 –

3

をすれば整数はPythonで不変であるので、しかし、それはあります。 、新しい番号を作成し、NUMに割り当てているあなたが代わりにnum(したがってa)を変更していない

a = 4 
num = a 
num *= 2 
print(a) 

:だからaは、このコードを実行するとき、それは変更されません同じ理由で変更されません。

3

引数は実際には値によって渡されます。この関数は、変数自体ではなく、変数が参照するオブジェクトに渡されます。関数は呼び出し元の変数を再バインドできません。関数は不変オブジェクトを変更することはできませんが、変更可能なオブジェクトを変更(要求変更)することができます。

+3

技術的には、割り当てによって渡されます。したがって、引数は引数が指すオブジェクトに割り当てられます。これは、代入が変数を変更し、メソッド呼び出しがオブジェクトを変更している間に、パラメータを再割り当てすることによって引数が再割り当てされない理由です。 – Sean

+1

@Sean、これは「値渡し」と呼ばれます –

1

これは関数呼び出しのセマンティクスではなく、割り当てのセマンティクスです。 Pythonの割り当てでは、元のオブジェクトを上書きするのではなく、参照を再バインドします。これは、例のコードが8の代わりに4を出力する理由です。オブジェクトの変更可能性とは何の関係もありません。* =演算子はミューテータではなく、乗算の後に割り当てられます。ここでnum * = 2は、その機能の 'num'という名前を値 'num * 2'の新しいオブジェクトに基本的に再バインドしています。渡された元の値は変更されません。

+0

「* =」について:http://stackoverflow.com/questions/823561/what-does-mean-in-python/823878#823878 –

関連する問題