web-dev-qa-db-ja.com

Pythonの参照による整数の受け渡し

Pythonで参照によって整数を渡すにはどうすればよいですか?

関数に渡す変数の値を変更したい。 Pythonのすべてが値渡しであることを読みましたが、簡単なトリックが必要です。たとえば、Javaでは、IntegerLongなどの参照型を渡すことができます。

  1. 参照によって整数を関数に渡すにはどうすればよいですか?
  2. ベストプラクティスは何ですか?
64

Pythonではそのようには機能しません。 Pythonは、オブジェクトへの参照を渡します。関数の中にオブジェクトがあります-そのオブジェクトを自由に変更できます(可能な場合)。ただし、整数は不変です。回避策の1つは、変更可能な整数をコンテナに渡すことです。

def change(x):
    x[0] = 3

x = [1]
change(x)
print x

これはせいぜいい/不器用ですが、Pythonでこれ以上改善するつもりはありません。その理由は、Pythonでは、割り当て(=)が右側の結果であるオブジェクトを受け取り、それを左側にあるものにバインドする*(または適切な関数に渡す)ためです。

これを理解すると、関数内の不変オブジェクトの値を変更する方法がない理由がわかります。不変であるため、その属性を変更することはできません。これは、実際には新しいオブジェクト(古いオブジェクトとは異なる)を作成し、古いオブジェクトがローカル名前空間に持っていた名前を付けているためです。

通常、回避策は、単純にreturn目的のオブジェクトです。

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

*上記の最初の例の場合、3は実際にx.__setitem__に渡されます。

81
mgilson

参照渡しする必要がある場合のほとんどは、呼び出し元に複数の値を返す必要がある場合です。 「ベストプラクティス」は、複数の戻り値を使用することです。これは、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
23
Gabe

実際、ベストプラクティスは、一歩下がって、本当にこれを行う必要があるかどうかを尋ねることです。 なぜ関数に渡す変数の値を変更しますか?

迅速なハックのためにそれを行う必要がある場合、最も迅速な方法は、整数を保持するlistを渡し、mgilsonの答えが示すように、その使用ごとに[0]を付けることです。

より重要なことを行う必要がある場合は、属性としてclassを持つintを記述してください。そうすれば、それを設定することができます。もちろん、これによりクラスと属性に適切な名前を付ける必要があります。何も考えられない場合は、戻って文を数回読み直し、listを使用します。

より一般的には、いくつかのJavaイディオムを直接Pythonに移植しようとしている場合、それは間違っています。直接対応するものがある場合(static/@staticmethodのように)でも、ほとんどのPythonプログラムで使用したいという理由だけでそれを使用したくないJava。

6
abarnert

Pythonでは、Javaの非プリミティブのように、すべての値は参照(オブジェクトへのポインター)です。また、Javaと同様、Pythonには値渡しのみがあります。したがって、意味的には、それらはほとんど同じです。

あなたはあなたの質問でJavaに言及しているので、私はあなたがJavaであなたが望むものをどのように達成するかを見たいです。 Javaで表示できる場合は、Pythonでもまったく同じ方法で表示できます。

2
newacct

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

正確に値を直接渡すのではなく、渡されたように使用します。

x = 7
def my_method():
    nonlocal x
    x += 1
my_method()
print(x) # 8

警告:

  • nonlocalはpython 3で導入されました
  • 囲むスコープがグローバルスコープの場合、globalの代わりにnonlocalを使用します。
1
Uri

古い空の型のトリックは、長さ1のリストのトリックよりも少し自己文書化されているかもしれません。

def inc_i(v):
    v.i += 1

x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)
1
mheyman

多分それはPythonの方法ではありませんが、あなたはこれを行うことができます

import ctypes

def incr(a):
    a += 1

x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref
1
Sergey Kovalev
class PassByReference:
    def Change(self, var):
        self.a = var
        print(self.a)
s=PassByReference()
s.Change(5)     
1
shruti

Pythonでは、すべてが値で渡されますが、何らかの状態を変更する場合は、メソッドに渡されるリストまたはオブジェクト内の整数の値を変更できます。

0
recursive