12901 Stimmen

Was bewirkt das Schlüsselwort "yield"?

Wozu dient die yield Schlüsselwort in Python? Was bewirkt es?

Ich versuche zum Beispiel, folgenden Code zu verstehen 1 :

def _get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  

Und das ist der Anrufer:

result, candidates = [], [self]
while candidates:
    node = candidates.pop()
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

Was passiert, wenn die Methode _get_child_candidates aufgerufen wird? Wird eine Liste zurückgegeben? Ein einzelnes Element? Wird sie erneut aufgerufen? Wann werden die nachfolgenden Aufrufe beendet?


1. Dieses Stück Code wurde von Jochen Schulz (jrschulz) geschrieben, der eine großartige Python-Bibliothek für metrische Räume entwickelt hat. Dies ist der Link zum vollständigen Quellcode: <a href="https://well-adjusted.de/~jrspieker/mspace/" rel="noreferrer">Modul mspace </a>.

74voto

redbandit Punkte 2013

Zusammenfassend lässt sich sagen, dass die yield Anweisung verwandelt Ihre Funktion in eine Fabrik, die ein spezielles Objekt namens generator die den Körper Ihrer ursprünglichen Funktion umschließt. Wenn die generator iteriert wird, führt es Ihre Funktion aus, bis es die nächste yield setzt dann die Ausführung aus und wertet den Wert aus, der an yield . Dieser Vorgang wird bei jeder Iteration wiederholt, bis der Ausführungspfad die Funktion verlässt. Zum Beispiel,

def simple_generator():
    yield 'one'
    yield 'two'
    yield 'three'

for i in simple_generator():
    print i

gibt einfach aus

one
two
three

Die Leistung ergibt sich aus der Verwendung des Generators mit einer Schleife, die eine Sequenz berechnet. Der Generator führt die Schleife aus und hält jedes Mal an, um das nächste Ergebnis der Berechnung zu "liefern", auf diese Weise berechnet er eine Liste im laufenden Betrieb.

Angenommen, Sie möchten eine eigene range Funktion, die einen iterierbaren Bereich von Zahlen erzeugt, könnten Sie so vorgehen,

def myRangeNaive(i):
    n = 0
    range = []
    while n < i:
        range.append(n)
        n = n + 1
    return range

und verwenden Sie es wie folgt;

for i in myRangeNaive(10):
    print i

Dies ist jedoch ineffizient, weil

  • Sie erstellen ein Array, das Sie nur einmal verwenden (dadurch wird Speicherplatz verschwendet)
  • Dieser Code durchläuft das Array sogar zweimal :(

Glücklicherweise waren Guido und sein Team so großzügig, Generatoren zu entwickeln, damit wir genau das tun konnten;

def myRangeSmart(i):
    n = 0
    while n < i:
       yield n
       n = n + 1
    return

for i in myRangeSmart(10):
    print i

Bei jeder Iteration wird nun eine Funktion des Generators namens next() führt die Funktion aus, bis sie entweder eine "yield"-Anweisung erreicht, bei der sie anhält und den Wert "ausgibt", oder bis sie das Ende der Funktion erreicht. In diesem Fall beim ersten Aufruf, next() führt bis zur Yield-Anweisung aus und gibt 'n' aus, beim nächsten Aufruf führt er die Inkrement-Anweisung aus, springt zurück zur 'while'-Anweisung, wertet sie aus, und wenn sie wahr ist, hält er an und gibt wieder 'n' aus, so geht es weiter, bis die while-Bedingung falsch zurückkommt und der Generator zum Ende der Funktion springt.

69voto

Kaleem Ullah Punkte 6183

Yield ist ein Objekt

A return in einer Funktion gibt einen einzigen Wert zurück.

Wenn Sie wollen eine Funktion zur Rückgabe einer großen Menge von Werten verwenden yield .

Noch wichtiger ist, yield ist eine Barriere .

wie die Barriere in der CUDA-Sprache, wird die Kontrolle nicht übertragen, bis sie abgeschlossen ist.

Das heißt, der Code in Ihrer Funktion wird von Anfang an ausgeführt, bis er auf yield . Dann wird der erste Wert der Schleife zurückgegeben.

Bei jedem weiteren Aufruf wird die Schleife, die Sie in die Funktion geschrieben haben, ein weiteres Mal durchlaufen und der nächste Wert zurückgegeben, bis es keinen Wert mehr zurückzugeben gibt.

67voto

Tom Fuller Punkte 4941

Viele Menschen verwenden return statt yield aber in einigen Fällen yield können effizienter und einfacher zu handhaben sein.

Hier ist ein Beispiel, das yield ist definitiv am besten für:

return (in Funktion)

import random

def return_dates():
    dates = [] # With 'return' you need to create a list then return it
    for i in range(5):
        date = random.choice(["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th"])
        dates.append(date)
    return dates

Ertrag (in Funktion)

def yield_dates():
    for i in range(5):
        date = random.choice(["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th"])
        yield date # 'yield' makes a generator automatically which works
                   # in a similar way. This is much more efficient.

Aufrufen von Funktionen

dates_list = return_dates()
print(dates_list)
for i in dates_list:
    print(i)

dates_generator = yield_dates()
print(dates_generator)
for i in dates_generator:
    print(i)

Beide Funktionen bewirken das Gleiche, aber yield verwendet drei statt fünf Zeilen und hat eine Variable weniger, um die man sich kümmern muss.

Das ist das Ergebnis des Codes:

Output

Wie Sie sehen können, tun beide Funktionen dasselbe. Der einzige Unterschied ist return_dates() gibt eine Liste und yield_dates() ergibt einen Generator.

Ein Beispiel aus dem wirklichen Leben wäre das zeilenweise Lesen einer Datei oder die Erstellung eines Generators.

57voto

Bahtiyar Özdere Punkte 1654

Le site yield Schlüsselwort sammelt einfach die zurückgegebenen Ergebnisse. Denken Sie an yield wie return +=

55voto

Will Dereham Punkte 936

yield ist wie ein Rückgabeelement für eine Funktion. Der Unterschied ist, dass das yield Element verwandelt eine Funktion in einen Generator. Ein Generator verhält sich genau wie eine Funktion, bis etwas "ausgegeben" wird. Der Generator hält an, bis er das nächste Mal aufgerufen wird, und setzt dann genau an der Stelle fort, an der er begonnen hat. Sie können eine Sequenz aller 'yielded' Werte in einem erhalten, indem Sie list(generator()) .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X