Ich habe eine in if-elif-elif-else-Anweisung, in der 99% der Zeit die else-Anweisung ausgeführt wird:
if something == 'this':
doThis()
elif something == 'that':
doThat()
elif something == 'there':
doThere()
else:
doThisMostOfTheTime()
Dieses Konstrukt wird viel gemacht , aber da es alle Bedingungen durchläuft, bevor es die anderen trifft, habe ich das Gefühl, dass dies nicht sehr effizient ist, geschweige denn Pythonic. Auf der anderen Seite muss es wissen, ob eine dieser Bedingungen erfüllt ist, also sollte es es trotzdem testen.
Weiß jemand, ob und wie dies effizienter gemacht werden könnte oder ist dies einfach der bestmögliche Weg, dies zu tun?
python
performance
if-statement
kramer65
quelle
quelle
sort
die Dinge, auf denen Sie Ihre if / else ... -Kette ausführen, so dass alle Elemente, für die eine der Bedingungen übereinstimmt, an einem Ende und alle anderen am anderen Ende sind? Wenn ja, könnten Sie sehen, ob das schneller / eleganter ist oder nicht. Denken Sie jedoch daran, dass es zu früh ist, sich über die Optimierung Gedanken zu machen, wenn es keine Leistungsprobleme gibt.if not something.startswith("th"): doThisMostOfTheTime()
einen weiteren Vergleich in derelse
Klausel durchführen.something
oder werden ähnliche Vergleiche mehrmals mit demselben Wert durchgeführt?Antworten:
Der Code...
... sieht so aus, als ob es schneller sein sollte, aber es ist tatsächlich langsamer als das
if
...elif
...else
Konstrukt, weil es eine Funktion aufrufen muss, was in einer engen Schleife einen erheblichen Leistungsaufwand bedeuten kann.Betrachten Sie diese Beispiele ...
1.py
2.py
3.py
4.py
... und notieren Sie die benötigte CPU-Zeit ...
... mit der Benutzerzeit von
time(1)
.Option 4 hat den zusätzlichen Speicheraufwand für das Hinzufügen eines neuen Elements für jeden einzelnen Schlüsselfehler. Wenn Sie also eine unbegrenzte Anzahl unterschiedlicher Schlüsselfehler erwarten, würde ich Option 3 wählen, die immer noch eine erhebliche Verbesserung darstellt das ursprüngliche Konstrukt.
quelle
dict
langsamer ist, aber dann zeigen Ihre Timings tatsächlich, dass es die zweitschnellste Option ist.dict.get()
ist langsamer, was ist2.py
- das langsamste von allen.Ich würde ein Wörterbuch erstellen:
Verwenden Sie jetzt nur:
Wird
something
imoptions
Diktat nicht gefunden,dict.get
wird der Standardwert zurückgegebendoThisMostOfTheTime
Einige Timing-Vergleiche:
Skript:
Ergebnisse:
Für
10**5
nicht vorhandene Schlüssel und 100 gültige Schlüssel:Für ein normales Wörterbuch ist die Überprüfung des Schlüssels
key in options
hier am effizientesten:quelle
options = collections.defaultdict(lambda: doThisMostOfTheTime, {'this': doThis,'that' :doThat, 'there':doThere}); options[something]()
ist geringfügig effizienter.options
Diktat trennen , um zu vermeiden, dass es neu erstellt wird, wodurch ein Teil (aber nicht die gesamte) Logik weit vom Verwendungsort entfernt wird. Trotzdem schöner Trick!try: options[key]() except KeyError: doSomeThingElse()
(daif key in options: options[key]()
Sie das Wörterbuch zweimalkey
Können Sie Pypy verwenden?
Wenn Sie Ihren Originalcode behalten, ihn aber auf Pypy ausführen, beschleunigt sich das für mich um das 50-fache.
CPython:
Pypy:
quelle
Hier ein Beispiel für ein if mit dynamischen Bedingungen, das in ein Wörterbuch übersetzt wurde.
Dies ist ein Weg, aber möglicherweise nicht der pythonischste, da er weniger lesbar ist und für den Python nicht fließend ist.
quelle
Die Leute warnen
exec
aus Sicherheitsgründen, aber dies ist ein idealer Fall dafür.Es ist eine einfache Zustandsmaschine.
quelle