it-swarm.com.de

Übergeben einer Ganzzahl als Referenz in Python

Wie kann ich eine ganze Zahl als Referenz in Python übergeben?

Ich möchte den Wert einer Variablen ändern, die ich an die Funktion übergeben habe. Ich habe gelesen, dass alles in Python nach Wert übergeben wird, aber es muss einen einfachen Trick geben. In Java könnten Sie beispielsweise die Referenztypen Integer, Long usw. übergeben.

  1. Wie kann ich eine Ganzzahl per Referenz in eine Funktion übergeben?
  2. Was sind die Best Practices?
57

In Python funktioniert das nicht ganz so. Python übergibt Verweise auf Objekte. In Ihrer Funktion haben Sie ein Objekt - Sie können dieses Objekt (wenn möglich) ändern. Ganzzahlen sind jedoch unveränderlich . Eine Problemumgehung besteht darin, die Ganzzahl in einem Container zu übergeben, der mutiert werden kann:

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

x = [1]
change(x)
print x

Das ist im besten Fall hässlich/ungeschickt, aber Sie werden in Python nichts Besseres tun. Der Grund dafür ist, dass die Zuweisung (=) in Python das Objekt der rechten Seite übernimmt und an das, was sich auf der linken Seite befindet * bindet (oder es an die entsprechende Funktion weitergibt).

Wenn Sie dies verstehen, können Sie sehen, warum es keine Möglichkeit gibt, den Wert eines unveränderlichen Objekts in einer Funktion zu ändern. Sie können keine Attribute ändern, da sie unveränderlich sind, und Sie können der "Variablen" nicht einfach eine neue zuweisen Wert, da Sie tatsächlich ein neues Objekt erstellen (das sich vom alten unterscheidet) und ihm den Namen geben, den das alte Objekt im lokalen Namespace hatte.

Normalerweise besteht die Problemumgehung darin, einfach return das gewünschte Objekt zurückzugeben:

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

* Im ersten Beispielfall wird 3 tatsächlich an x.__setitem__ übergeben.

74
mgilson

In den meisten Fällen, in denen Sie als Referenz übergeben werden müssen, müssen Sie dem Anrufer mehr als einen Wert zurückgeben. Eine "bewährte Methode" ist die Verwendung mehrerer Rückgabewerte. Dies ist in Python viel einfacher als in Sprachen wie Java.

Hier ist ein einfaches Beispiel:

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
21
Gabe

In der Tat ist es am besten, wenn Sie einen Schritt zurücktreten und fragen, ob Sie dies wirklich tun müssen. Warum möchten Sie den Wert einer Variablen ändern, die Sie an die Funktion übergeben?

Wenn Sie es für einen schnellen Hack tun müssen, ist der schnellste Weg, eine list mit der ganzen Zahl zu übergeben und jeden Code mit einem [0] zu versehen, wie die Antwort von mgilson zeigt.

Wenn Sie es für etwas Wichtigeres tun müssen, schreiben Sie eine class, die eine int als Attribut enthält, so dass Sie es einfach setzen können. Natürlich zwingt man Sie dazu, einen guten Namen für die Klasse und für das Attribut zu finden. Wenn Ihnen nichts einfällt, lesen Sie den Satz ein paar Mal erneut und verwenden Sie dann die Variable list.

Wenn Sie versuchen, ein Java-Idiom direkt in Python zu portieren, machen Sie es im Allgemeinen falsch. Selbst wenn etwas direkt übereinstimmt (wie bei static/@staticmethod), möchten Sie es in den meisten Python-Programmen nicht verwenden, nur weil Sie es in Java verwenden.

5
abarnert
class PassByReference:
    def Change(self, var):
        self.a = var
        print(self.a)
s=PassByReference()
s.Change(5)     
2
shruti

In Python ist jeder Wert eine Referenz (ein Zeiger auf ein Objekt), genau wie Nichtprimitive in Java. Wie Java hat auch Python nur Wertübergabe. Semantisch sind sie also ziemlich gleich.

Da Sie Java in Ihrer Frage erwähnen, würde ich gerne sehen, wie Sie in Java das erreichen, was Sie wollen. Wenn Sie es in Java zeigen können, kann ich Ihnen zeigen, wie es in Python genau gleichwertig ist.

1
newacct

Ein numpy-Einzelelement-Array ist veränderbar und kann für die meisten Zwecke so ausgewertet werden, als wäre es eine numerische Python-Variable. Daher ist es ein bequemer Container für Referenznummern als eine Liste mit einem Element.

    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)

ausgabe:

3
1
Tal

Vielleicht ist es nicht pythonisch, aber Sie können dies tun

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

Einen Wert nicht direkt direkt übergeben, sondern so verwenden, als wäre er übergeben worden.

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

Vorsichtsmaßnahmen:

  • nonlocal wurde in Python 3 eingeführt
  • Wenn der umgebende Bereich der globale ist, verwenden Sie global anstelle von nonlocal.
0
Uri

Etwas mehr selbstdokumentierend als der Trick list-of-length-1 ist der alte Trick vom leeren Typ:

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

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

In Python wird alles als Wert übergeben. Wenn Sie jedoch einen Status ändern möchten, können Sie den Wert einer Ganzzahl in einer Liste oder einem Objekt ändern, die bzw. das an eine Methode übergeben wird.

0
recursive