2017-11-23 1 views
1

Ich habe einige Anwendungsfälle, in denen ich Generatorfunktionen ausführen muss, ohne sich um die erhaltenen Elemente zu kümmern.
Ich kann sie nicht generatorfreie Funktionen machen, weil ich in anderen Anwendungsfällen sicherlich die erhaltenen Werte brauche.Einfachere Möglichkeit, eine Generatorfunktion zu betreiben, ohne sich um die Elemente zu kümmern

Ich benutze derzeit eine triviale Self-made-Funktion, um die Generatoren zu erschöpfen.

def exhaust(generator): 
    for _ in generator: 
     pass 

Ich fragte mich, ob es einen einfacheren Weg, das zu tun, was ich vermisst habe?

bearbeiten einem Anwendungsfall Folgende:

def create_tables(fail_silently=True): 
    """Create the respective tables.""" 

    for model in MODELS: 
     try: 
      model.create_table(fail_silently=fail_silently) 
     except Exception: 
      yield (False, model) 
     else: 
      yield (True, model) 

In einem bestimmten Kontext, ich kümmere mich um die Fehler und Erfolgswerte ...

for success, table in create_tables(): 
    if success: 
     print('Creation of table {} succeeded.'.format(table)) 
    else: 
     print('Creation of table {} failed.'.format(table), file=stderr) 

... und in einigen Ich will nur die laufen Funktion "blind":

exhaust(create_tables()) 
+2

* Warum? * Was ist der Zweck solcher Funktionen? Es riecht nach einem größeren Designproblem, geschweige denn nach einem XY-Problem. – DeepSpace

+0

Das scheint schon ziemlich einfach zu sein, nein? –

+0

Aktualisiert mit tatsächlichen Anwendungsfall. –

Antwort

3

Das Einrichten einer for-Schleife dafür könnte relativ teuer sein, wenn man bedenkt, dass eine Schleife in Python grundsätzlich eine sukzessive Ausführung von einfachen Zuweisungsanweisungen ist; Sie werden die n (Anzahl der Elemente im Generator) Zuweisungen ausführen, nur um anschließend die Zuweisungsziele zu verwerfen.

Sie können den Generator stattdessen auf eine Nulllänge einspeisen deque; verbraucht bei C-Geschwindigkeit und bis Speicher nicht wie bei list und anderen Callables verwenden, die Iteratoren/Generatoren materialisieren:

from collections import deque 

def exhaust(generator): 
    deque(generator, maxlen=0) 

vom consume itertools Rezepte genommen.

+0

Läuft auch eine 'for'-Schleife nicht mit C-Geschwindigkeit und verwendet denselben Speicher? Vielleicht ein paar Timings zeigen? –

+0

@Chris_Rands Ja, es läuft mit C-Geschwindigkeit, aber nicht vollständig, da Rückrufe zu Python gemacht werden, um die Schleife bis zum Abschluss zu wiederholen. Außerdem ist die wiederholte Zuweisung nur zusätzlicher Aufwand. –

+1

Die Verwendung von "deque" scheint nur ein kleines bisschen schneller zu sein als die vom OP vorgeschlagene einfache Schleife; mit einer 'consume.generator'-Funktion, die die ersten 1000 Zahlen ergibt, benötigt 'for _ in consume.generator(): pass' 71,8 usec pro Schleife für mich,' deque (consume.generator(), maxlen = 0) ' dauert 67,4 (nach Zeit). –

1

Basierend auf Ihrem Anwendungsfall ist es schwer vorstellbar, dass es genügend Tabellen geben würde, die Sie erstellen müssten, um die Leistung zu berücksichtigen.

Darüber hinaus wird Tabellenerstellung viel teurer als Iteration sein.

Also die for-Schleife, die Sie bereits haben, scheint die einfachste und pythonischste Lösung zu sein - in diesem Fall.

Verwandte Themen