Ich habe ein einfaches Skript geschrieben, um ein "logisches Puzzle" zu lösen, die Art von Puzzle aus der Schule, wo man eine Reihe von Regeln bekommt und dann die Lösung für Probleme finden kann wie "Es gibt fünf Musiker namens A, B , C, D und E spielen in einem Konzert, jeder spielt nacheinander ... wenn A vor B geht und D nicht zuletzt ... wie ist die Reihenfolge, wer wann spielt? " usw.Gibt es ein Python-Idiom zum Auswerten einer Liste von Funktionen/Ausdrücken mit Kurzschlüssen?
mögliche Lösungen zu bewerten, schrieb ich jede „Regel“ als eine separate Funktion, die, wenn eine mögliche Lösung (dargestellt einfach als Liste von Strings) gültig ist, zum Beispiel
#Fifth slot must be B or D
def rule1(solution):
return solution[4] == 'B' or solution[4] == 'D'
#There must be at least two spots between A and B
def rule2(solution):
returns abs(solution.index('A') - solution.index('B')) >= 2
#etc...
ich bewerten würde Ich bin daran interessiert, den Pythonic-Weg zu finden, um zu testen, ob eine mögliche Lösung alle solchen Regeln besteht, mit der Fähigkeit, die Bewertung von Regeln zu stoppen, nachdem die erste fehlgeschlagen ist.
Zuerst schrieb ich eine möglichst einfache Sache:
def is_valid(solution):
return rule1(solution) and rule2(solution) and rule3(solution) and ...
Aber das schien ziemlich hässlich. Ich dachte, vielleicht könnte ich dies mit so etwas wie eine Liste Verständnis etwas elegantere lesen ...
def is_valid(solution)
rules = [rule1, rule2, rule3, rule4, ... ]
return all([r(solution) for f in rules])
... aber dann merkte ich, dass, da die Liste Verständnis vor der all()
Funktion erzeugt wird, wird beurteilt, dass dies hat den Nebeneffekt, dass sie überhaupt nicht kurzgeschlossen sind - jede Regel wird ausgewertet, selbst wenn die erste False
zurückgibt.
Also meine Frage ist: Gibt es eine mehr Pythonic/functional Möglichkeit, eine Liste von True
/False
Ausdrücke, mit Kurzschlüssen bewerten zu können, ohne die Notwendigkeit, eine lange Liste von return f1(s) and f2(s) and f3(s) ...
zu schreiben?
Also ist der grundlegende Unterschied hier die Klammern in 'return all ([r (Lösung) für r in Regeln])', damit keine Liste aller Ergebnisse zu erstellen, bevor 'all()' ausgewertet wird? –
Ja. In beiden Fällen wird das Argument für "all" ausgewertet, bevor es übergeben wird, aber die Auswertung eines Listenverständnisses erstellt die gesamte Liste im Speicher, während die Auswertung eines Generatorausdrucks ein Generatorobjekt erzeugt, das die Elemente bei Bedarf lädt. – katrielalex
Perfekt, das macht sehr viel Sinn - danke –