Frage

In Python können Sie haben eine Funktion mehrere Werte zurückgeben. Hier ist ein konstruiertes Beispiel:

def divide(x, y):
    quotient = x/y
    remainder = x % y
    return quotient, remainder  

(q, r) = divide(22, 7)

Dieses sehr nützlich scheint, aber es sieht aus wie es auch missbraucht werden kann ( „Well..function X berechnet bereits, was wir als ein Zwischenwert benötigen. Lassen Sie uns haben X den Wert zurückgeben auch“).

Wann sollte man die Grenze ziehen und eine andere Methode definieren?

War es hilfreich?

Lösung

Absolut (für das Beispiel, das Sie zur Verfügung gestellt).

Tupeln sind Bürger erster Klasse in Python

Es gibt eine eingebaute Funktion divmod() , das tut genau das.

q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

Es gibt andere Beispiele: zip, enumerate, dict.items.

for i, e in enumerate([1, 3, 3]):
    print "index=%d, element=%s" % (i, e)

# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or 
d = dict(zip(adict.values(), adict.keys()))

BTW, Klammern sind nicht notwendig, die meiste Zeit. Zitat aus Python Library Reference :

  

Tupeln in einer Reihe von Arten aufgebaut werden:

     
      
  • ein Paar Klammern Verwenden des leeren Tupel zu bezeichnen: ()
  •   
  • einen nachlauf Komma für einen Singleton Tupel verwenden: a, oder (a,)
  •   
  • Trennen Artikel mit Komma: a, b, c oder (a, b, c)
  •   
  • Das Tupel () eingebaut: Tupel () oder Tupel (abzählbaren)
  •   

Funktionen sollten einzigen Zweck

dienen

Sie sollten daher ein einzelnes Objekt zurück. In Ihrem Fall ist dieses Objekt ein Tupel. Betrachten wir Tupel als Ad-hoc-Verbindung Datenstruktur. Es gibt Sprachen, wo fast jede einzelne Funktion mehrere Werte (Liste in Lisp) zurück.

Manchmal reicht es aus, (x, y) statt Point(x, y) zurückzukehren.

Named Tupel

Mit der Einführung der genannten Tupel in Python 2.6 ist es vorzuziehen, in vielen Fällen genannt Tupel statt Klar Tupel zurück.

>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
...   print(i)
...
0
1

Andere Tipps

Zunächst beachten Sie, dass Python für die folgende (keine Notwendigkeit für die Klammern) erlaubt:

q, r = divide(22, 7)

In Bezug auf Ihre Frage, gibt es keine feste Regel, so oder so. Für einfache (und in der Regel künstlich) Beispiele, mag es scheint, dass es immer möglich ist, für eine gegebene Funktion einen einzigen Zweck zu haben, in einem einzigen Wert zur Folge hat. Wenn jedoch Python für reale Anwendungen verwenden, können Sie schnell in vielen Fällen laufen, wo mehrere Werte Rückkehr notwendig ist, und führt zu saubereren Code.

Also, ich würde sagen, tun, was Sinn macht, und nicht versuchen, zu einer künstlichen Konvention zu entsprechen. Python unterstützt mehrere Rückgabewerte, so dass es verwenden, wenn angemessen.

Das Beispiel Sie geben, ist eigentlich eine Python eingebaute Funktion, genannt divmod. Also jemand, irgendwann in der Zeit, dachte, dass es pythonic genug war, in der Kernfunktionalität gehört.

Für mich, wenn es den Code sauberer macht, ist es pythonic. Vergleichen Sie diese zwei Codeblöcke:

seconds = 1234
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)

seconds = 1234
minutes = seconds / 60
seconds = seconds % 60
hours = minutes / 60
minutes = minutes % 60

Ja, mehrere Werte zurückgegeben werden (das heißt, ein Tupel) ist auf jeden Fall pythonic. Wie andere haben darauf hingewiesen, gibt es Beispiele in der Python-Standardbibliothek sowie in renommierten Python-Projekten viel. Zwei weitere Kommentare:

  1. mehr Werte zurückkehrend ist manchmal sehr, sehr nützlich. Nehmen wir zum Beispiel ein Verfahren, das gegebenenfalls ein Ereignis behandelt (einen Wert dabei zurückkehrt) und auch wieder Erfolg oder Misserfolg. Dies könnte in einer Kette von Verantwortung Mustern entstehen. In anderen Fällen mögen Sie mehr, eng verknüpfte Datenstücke --- wie im Beispiel gegeben zurückzukehren. In dieser Einstellung ist es, mehrere Werte zurückgegeben werden ähnlich eine einzelne Instanz eines anonymen Klasse mit mehreren Mitgliedsvariablen zurück.
  2. Pythons Umgang mit Methodenargumente erfordert die Fähigkeit, mehrere Werte direkt zurück. In C ++ können beispielsweise Verfahren Argumente als Referenz übergeben werden, so können Sie Ausgangswerte zu ihnen zusätzlich zu dem formalen Rückgabewert zuweisen. In Python werden Argumente übergeben "Verweis" (sondern im Sinne von Java, nicht C ++). Sie können keine neuen Werte Methodenargumente zuweisen und haben es außerhalb Methode Umfang wider. Zum Beispiel:

    // C++
    void test(int& arg)
    {
        arg = 1;
    }
    
    int foo = 0;
    test(foo); // foo is now 1!
    

    Vergleichen mit:

    # Python
    def test(arg):
        arg = 1
    
    foo = 0
    test(foo) # foo is still 0
    

Es ist definitiv pythonic. Die Tatsache, dass Sie mehrere Werte aus einer Funktion, den Text zurückkehren, können Sie in einer Sprache wie C haben würden, wo Sie brauchen eine Struktur für jede Kombination von Typen, die Sie irgendwo zurückkehren zu definieren.

Wenn Sie jedoch den Punkt erreichen, wo man etwas verrückt wie 10 Werte aus einer einzigen Funktion zurückkehren, sollten Sie ernsthaft in Erwägung ziehen sie in einer Klasse, weil an diesem Punkt zu bündeln wird es unhandlich.

ein Tupel Rückkehr cool. Beachten Sie auch die neue namedtuple das wurde in Python 2.6 hinzugefügt, die für Sie diese schmackhaft machen kann: http://docs.python.org/dev/library/collections. html # collections.namedtuple

OT: RSRE des Algol68 hat den kuriosen "/: =" Operator. zB.

INT quotient:=355, remainder;
remainder := (quotient /:= 113);

Geben eines Quotienten aus 3 und einem Rest von 16

Hinweis: typischerweise der Wert von „(x /: = y)“. Wird als Quotient verworfen „x“ durch Verweis zugeordnet ist, aber in RSRE Fall der zurückgegebene Wert ist der Rest

C.F. Integer Arithmetik - Algol68

Es ist in Ordnung, mehrere Werte mit einem Tupel für einfache Funktionen wie divmod zurückzukehren. Wenn es der Code lesbar macht, ist es Pythonic.

Wenn der Rückgabewert beginnt verwirrend zu werden, überprüfen Sie, ob die Funktion zu viel tut und teilen Sie es, wenn es ist. Wenn ein großes Tupel wird wie ein Objekt verwendet wird, macht es zu einem Objekt. Bedenken Sie auch genannt Tupeln verwenden, die 2,6 Teil der Standard-Bibliothek in Python sein.

Ich bin ziemlich neu in Python, aber die Tupel Technik scheint sehr pythonic zu mir. Allerdings habe ich eine andere Idee hatte, die Lesbarkeit verbessern kann. mit einem Dictionary ermöglicht den Zugriff auf die verschiedenen Werte mit Namen statt Position. Zum Beispiel:

def divide(x, y):
    return {'quotient': x/y, 'remainder':x%y }

answer = divide(22, 7)
print answer['quotient']
print answer['remainder']
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top