Pythonで参照によって整数を渡すにはどうすればよいですか?
関数に渡す変数の値を変更したい。Pythonのすべてが値渡しであることを読みましたが、簡単なトリックが必要です。たとえば、Javaでは、あなたはの参照型渡すことができInteger
、Long
など
- 参照によって整数を関数に渡すにはどうすればよいですか?
- ベストプラクティスは何ですか?
Pythonで参照によって整数を渡すにはどうすればよいですか?
関数に渡す変数の値を変更したい。Pythonのすべてが値渡しであることを読みましたが、簡単なトリックが必要です。たとえば、Javaでは、あなたはの参照型渡すことができInteger
、Long
など
回答:
Pythonではそのようには機能しません。Pythonはオブジェクトへの参照を渡します。関数内にはオブジェクトがあります-(可能であれば)そのオブジェクトを自由に変更できます。ただし、整数は不変です。回避策の1つは、変更可能なコンテナーに整数を渡すことです。
def change(x):
x[0] = 3
x = [1]
change(x)
print x
これはせいぜい醜い/不器用ですが、Pythonでこれ以上うまくいくことはありません。その理由は、Pythonでは、代入(=
)が右側の結果であるオブジェクトを受け取り、それを左側にあるものにバインドするためです*(または適切な関数に渡します)。
これを理解すると、関数内の不変オブジェクトの値を変更する方法がない理由がわかります。不変であるため、その属性を変更することはできず、「変数」に新しいものを割り当てることはできません。これは、実際に新しいオブジェクト(古いオブジェクトとは異なる)を作成し、古いオブジェクトがローカル名前空間で持っていた名前を付けているためです。
通常、回避策は、必要なオブジェクトを返すことです。
def multiply_by_2(x):
return 2*x
x = 1
x = multiply_by_2(x)
*上記の最初の例では、3
実際にはに渡されx.__setitem__
ます。
C
。(たとえば、逆参照する必要はありません)。私のメンタルモデルでは、物事を「名前」や「オブジェクト」と考える方が簡単です。割り当ては、左側の「名前」を右側の「オブジェクト」にバインドします。関数を呼び出すときは、「オブジェクト」を渡します(関数内の新しいローカル名に効果的にバインドします)。
.
演算子は単に左側を逆参照します。演算子は言語によって異なる場合があります。
参照渡しが必要になるほとんどの場合は、複数の値を呼び出し元に返す必要がある場合です。「ベストプラクティス」は、複数の戻り値を使用することです。これは、Javaなどの言語よりもPythonで行う方がはるかに簡単です。
簡単な例を次に示します。
def RectToPolar(x, y):
r = (x ** 2 + y ** 2) ** 0.5
theta = math.atan2(y, x)
return r, theta # return 2 things at once
r, theta = RectToPolar(3, 4) # assign 2 things at once
実際、ベストプラクティスは、一歩下がって、本当にこれを行う必要があるかどうかを尋ねることです。関数に渡す変数の値を変更したいのはなぜですか?
簡単なハックのためにそれを行う必要がある場合、最も簡単な方法はlist
、整数を保持することを渡し、[0]
mgilsonの答えが示すように、それを使用するたびにそれを回避することです。
より重要なことのためにそれを行う必要がある場合は、属性としてclass
を持っているint
を記述して、それを設定するだけです。もちろん、これにより、クラスと属性の適切な名前を思い付く必要があります。何も考えられない場合は、戻って文を数回読み直してから、を使用してくださいlist
。
より一般的には、JavaイディオムをPythonに直接移植しようとしている場合、それは間違っています。(static
/のように@staticmethod
)直接対応するものがある場合でも、Javaで使用するという理由だけで、ほとんどのPythonプログラムでそれを使用することは望ましくありません。
numpyの単一要素アレイは可変とまだほとんどの目的のためであり、それは数値Pythonの変数であるかのように、それを評価することができます。したがって、単一要素リストよりも便利な参照番号コンテナです。
import numpy as np
def triple_var_by_ref(x):
x[0]=x[0]*3
a=np.array([2])
triple_var_by_ref(a)
print(a+1)
出力:
3
たぶん、長さ1のリストのトリックよりも少し自己文書化するのは、古い空のタイプのトリックです。
def inc_i(v):
v.i += 1
x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)
Pythonでは、すべてが値によって渡されますが、ある状態を変更する場合は、メソッドに渡されるリストまたはオブジェクト内の整数の値を変更できます。
everything is passed by value
本当ではないからだと思います。引用ドキュメント:arguments are passed using call by value (where the value is always an object reference, not the value of the object)