In diesem Tutorial erkunden wir die Möglichkeiten der timeit
-Funktion aus dem timeit
-Modul von Python. Wir werden uns ansehen, wie man einfache Ausdrücke sowie ganze Funktionen in Python zeitlich messen kann.
Das Messen der Ausführungszeit Ihres Codes kann Ihnen helfen, die Performance eines bestimmten Codeabschnitts besser einzuschätzen und sogar die Bereiche zu identifizieren, die möglicherweise einer Optimierung bedürfen.
Zuerst werden wir die Syntax der timeit
-Funktion in Python kennenlernen. Anschließend werden wir anhand von Beispielen demonstrieren, wie Sie damit Codeblöcke und Funktionen in Ihrem Python-Projekt zeitlich messen können. Legen wir los!
Die Verwendung der Python timeit
-Funktion
Das timeit
-Modul ist Bestandteil der Python-Standardbibliothek. Sie können es also ganz einfach importieren:
import timeit
Die Syntax zur Anwendung der timeit
-Funktion aus dem timeit
-Modul sieht wie folgt aus:
timeit.timeit(stmt, setup, number)
Hierbei gilt:
stmt
repräsentiert den Codeausschnitt, dessen Ausführungszeit gemessen werden soll. Dies kann eine einfache Python-Zeichenkette, eine mehrzeilige Zeichenkette oder auch der Name einer aufrufbaren Funktion sein.setup
, wie der Name schon sagt, beinhaltet den Code, der nur einmalig ausgeführt werden muss, häufig als Vorbedingung für die Ausführung vonstmt
. Nehmen wir an, Sie möchten die Ausführungszeit für das Erstellen eines NumPy-Arrays messen. In diesem Fall wäre das Importieren von NumPy der Einrichtungscode und das eigentliche Erstellen die Anweisung, die zeitlich erfasst werden soll.number
gibt an, wie oftstmt
ausgeführt werden soll. Der Standardwert fürnumber
liegt bei 1 Million (1000000), Sie können diesen Parameter aber beliebig anpassen.
Nachdem wir nun die Syntax der timeit()
-Funktion verstanden haben, wollen wir uns einigen Codebeispielen zuwenden.
Zeitliche Messung einfacher Python-Ausdrücke
In diesem Abschnitt werden wir die Ausführungszeit einfacher Python-Ausdrücke mit timeit
messen.
Starten Sie eine Python-REPL und führen Sie die folgenden Codebeispiele aus. Hier werden wir die Ausführungszeit von Potenzierungs- und Ganzzahldivisionsoperationen für 10.000 und 100.000 Durchläufe ermitteln.
Beachten Sie, dass wir die zu messende Anweisung als Python-String übergeben und ein Semikolon verwenden, um die verschiedenen Ausdrücke innerhalb der Anweisung zu trennen.
>>> import timeit
>>> timeit.timeit('3**4;3//4',number=10000)
0.0004020999999738706
>>> timeit.timeit('3**4;3//4',number=100000)
0.0013780000000451764
Ausführen von Python timeit
über die Befehlszeile
Sie können timeit
auch direkt in der Kommandozeile verwenden. Hier ist das Befehlszeilenäquivalent zum Aufruf der timeit
-Funktion:
$ python -m timeit -n (number) -s (setup) (stmt)
python -m timeit
bedeutet, dass wirtimeit
als Hauptmodul aufrufen.-n
ist eine Befehlszeilenoption, die angibt, wie oft der Code ausgeführt werden soll. Dies entspricht demnumber
-Argument beim Funktionsaufruftimeit()
.- Mit der Option
-s
definieren Sie den Setup-Code.
Hier schreiben wir das vorherige Beispiel mit dem Befehlszeilenäquivalent um:
$ python -m timeit -n 100000 '3**4;3//4'
100000 loops, best of 5: 35.8 nsec per loop
In diesem Beispiel messen wir die Ausführungszeit der eingebauten Funktion len()
. Die Initialisierung der Zeichenkette ist der Setup-Code, der mit der Option -s
übergeben wird.
$ python -m timeit -n 100000 -s "string_1 = 'coding'" 'len(string_1)'
100000 loops, best of 5: 239 nsec per loop
Beachten Sie in der Ausgabe, dass wir die Ausführungszeit für „Best-of-5“-Läufe erhalten. Was bedeutet das? Wenn Sie timeit
in der Kommandozeile ausführen, wird die Wiederholungsoption -r
standardmäßig auf 5 gesetzt. Das heißt, die Ausführung von stmt
wird für die angegebene Anzahl von Wiederholungen fünfmal wiederholt, und die beste dieser Ausführungszeiten wird zurückgegeben.
Analyse von Methoden zum Umkehren von Strings mithilfe von timeit
Bei der Arbeit mit Python-Strings kann es erforderlich sein, diese umzukehren. Die zwei häufigsten Methoden dafür sind:
- Verwenden von String-Slicing
- Verwenden der
reversed()
-Funktion in Verbindung mit derjoin()
-Methode
Umkehren von Python-Strings mit String Slicing
Sehen wir uns an, wie String-Slicing funktioniert und wie man damit einen Python-String umkehren kann. Bei der Verwendung der Syntax some-string[start:stop]
wird ein Teil des Strings zurückgegeben, der am Index start
beginnt und sich bis zum Index stop-1
erstreckt. Betrachten wir ein Beispiel:
Nehmen wir die Zeichenkette „Python“. Der String hat eine Länge von 6, und die Liste der Indizes reicht von 0, 1, 2 bis 5.
>>> string_1 = 'Python'
Wenn Sie sowohl den Start- als auch den Stoppwert angeben, erhalten Sie einen String-Slice, der von start
bis stop-1
reicht. Daher gibt string_1[1:4]
‚yth‘ zurück.
>>> string_1 = 'Python'
>>> string_1[1:4]
'yth'
Wenn Sie den Startwert weglassen, wird standardmäßig der Wert Null verwendet, und das Segment beginnt beim Index Null und reicht bis stop – 1
.
Hier ist der Stoppwert 3, also beginnt der Slice bei Index 0 und geht bis Index 2.
>>> string_1[:3]
'Pyt'
Wenn Sie den Stoppindex nicht angeben, sehen Sie, dass der Slice am Startindex (1) beginnt und sich bis zum Ende des Strings erstreckt.
>>> string_1[1:]
'ython'
Wenn Sie sowohl den Start- als auch den Stoppwert ignorieren, wird ein Slice des gesamten Strings zurückgegeben.
>>> string_1[:]
'Python'
Lassen Sie uns einen Slice mit einem Schrittwert erstellen. Wir setzen die Start-, Stopp- und Schrittwerte auf 1, 5 bzw. 2. Wir erhalten einen Teil des Strings, der bei 1 beginnt und sich bis 4 erstreckt (ohne den Endpunkt 5), der jedes zweite Zeichen enthält.
>>> string_1[1:5:2]
'yh'
Wenn Sie einen negativen Schritt verwenden, können Sie einen Slice erhalten, der am Ende des Strings beginnt. Wenn der Schritt auf -2 gesetzt ist, ergibt string_1[5:2:-2]
den folgenden Slice:
>>> string_1[5:2:-2]
'nh'
Um eine umgekehrte Kopie des Strings zu erhalten, überspringen wir also die Start- und Stoppwerte und setzen den Schritt auf -1, wie gezeigt:
>>> string_1[::-1]
'nohtyP'
Zusammenfassend lässt sich sagen: string[::-1]
gibt eine umgekehrte Kopie des Strings zurück.
Umkehren von Strings mit eingebauten Funktionen und String-Methoden
Die eingebaute Funktion reversed()
in Python gibt einen umgekehrten Iterator über die Elemente des Strings zurück.
>>> string_1 = 'Python'
>>> reversed(string_1)
<reversed object at 0x00BEAF70>
Sie können also mit einer for-Schleife durch den umgekehrten Iterator iterieren:
for char in reversed(string_1):
print(char)
um auf die Elemente des Strings in umgekehrter Reihenfolge zuzugreifen.
# Ausgabe
n
o
h
t
y
P
Als Nächstes können Sie die Methode join()
auf dem umgekehrten Iterator mit der folgenden Syntax aufrufen:
.
Der folgende Code-Ausschnitt zeigt einige Beispiele, bei denen das Trennzeichen ein Bindestrich bzw. ein Leerzeichen ist.
>>> '-'.join(reversed(string1))
'n-o-h-t-y-P'
>>> ' '.join(reversed(string1))
'n o h t y P'
Hier benötigen wir kein Trennzeichen; setzen wir das Trennzeichen also auf einen leeren String, um eine umgekehrte Kopie des Strings zu erhalten:
>>> ''.join(reversed(string1))
'nohtyP'
Die Verwendung von ''.join(reversed(some-string))
gibt also eine umgekehrte Kopie des Strings zurück.
Vergleich der Ausführungszeiten mit timeit
Wir haben bisher zwei Methoden zum Umkehren von Python-Strings kennengelernt. Aber welche von beiden ist schneller? Finden wir es heraus.
In einem früheren Beispiel, in dem wir einfache Python-Ausdrücke gemessen haben, hatten wir keinen Setup-Code. Hier werden wir den Python-String umkehren. Während die String-Umkehroperation so oft ausgeführt wird, wie durch number
angegeben, ist der Setup-Code die Initialisierung des Strings, der nur einmal ausgeführt wird.
>>> import timeit
>>> timeit.timeit(stmt="string_1[::-1]", setup = "string_1 = 'Python'", number = 100000)
0.04951830000001678
>>> timeit.timeit(stmt = "''.join(reversed(string_1))", setup = "string_1 = 'Python'", number = 100000)
0.12858760000000302
Bei derselben Anzahl von Durchläufen zum Umkehren des gegebenen Strings ist die Methode des String-Slicings schneller als die Verwendung der Methode join()
in Kombination mit der Funktion reversed()
.
Zeitliche Messung von Python-Funktionen mit timeit
In diesem Abschnitt erfahren Sie, wie Sie Python-Funktionen mit der Funktion timeit
messen können. Für eine gegebene Liste von Strings gibt die folgende Funktion hasDigit
die Liste der Strings zurück, die mindestens eine Ziffer enthalten.
def hasDigit(somelist):
str_with_digit = []
for string in somelist:
check_char = (char.isdigit() for char in string)
if any(check_char):
str_with_digit.append(string)
return str_with_digit
Jetzt wollen wir die Ausführungszeit dieser Python-Funktion hasDigit()
mit timeit
messen.
Identifizieren wir zuerst die zu messende Anweisung (stmt
). Dies ist der Aufruf der Funktion hasDigit()
mit einer Liste von Strings als Argument. Als Nächstes definieren wir den Setup-Code. Können Sie sich vorstellen, was der Setup-Code sein sollte?
Damit der Funktionsaufruf erfolgreich ausgeführt werden kann, sollte der Setup-Code Folgendes beinhalten:
- Die Definition der Funktion
hasDigit()
- Die Initialisierung der Argumentenliste der Strings
Lassen Sie uns den Setup-Code in der Setup-Zeichenkette definieren, wie unten gezeigt:
setup = """
def hasDigit(somelist):
str_with_digit = []
for string in somelist:
check_char = (char.isdigit() for char in string)
if any(check_char):
str_with_digit.append(string)
return str_with_digit
thislist=('puffin3','7frost','blue')
"""
Als Nächstes können wir die Funktion timeit
verwenden und die Ausführungszeit der Funktion hasDigit()
für 100.000 Durchläufe erhalten.
import timeit
timeit.timeit('hasDigit(thislist)',setup=setup,number=100000)
# Ausgabe
0.2810094920000097
Fazit
Sie haben gelernt, wie Sie die timeit
-Funktion von Python verwenden, um Ausdrücke, Funktionen und andere aufrufbare Objekte zeitlich zu messen. Dies kann Ihnen helfen, Ihren Code zu bewerten, die Ausführungszeiten verschiedener Implementierungen derselben Funktion zu vergleichen und vieles mehr.
Fassen wir noch einmal zusammen, was wir in diesem Tutorial gelernt haben. Sie können die Funktion timeit()
mit der Syntax timeit.timeit(stmt=…,setup=…,number=…)
verwenden. Alternativ können Sie timeit
in der Befehlszeile ausführen, um kurze Code-Schnipsel zu messen.
Als nächsten Schritt können Sie untersuchen, wie Sie andere Python-Profilerstellungspakete wie line-profiler
und memprofiler
verwenden, um Ihren Code für Zeit bzw. Speicher zu profilieren.
Als Nächstes werden Sie lernen, wie man den Zeitunterschied in Python berechnet.