I denne veiledningen skal vi undersøke hvordan man anvender timeit
-funksjonen fra Pythons timeit
-modul. Vi vil se på hvordan man kan måle tidsbruken for enkle uttrykk og funksjoner i Python.
Å analysere hvor lang tid koden din bruker på å utføre, gir deg et overslag over kjøretiden for et bestemt kodeområde. Dette kan hjelpe deg med å identifisere deler av koden som kan trenge optimalisering.
Vi starter med å se på hvordan timeit
-funksjonen i Python er bygd opp, før vi fortsetter med praktiske eksempler. Målet er å forstå hvordan du kan bruke modulen til å måle ytelsen til både kodeblokker og funksjoner. La oss komme i gang!
Hvordan bruke Python timeit
-funksjonen
timeit
-modulen er en standard del av Python-biblioteket, og den kan enkelt importeres:
import timeit
Slik er syntaksen for timeit
-funksjonen:
timeit.timeit(stmt, setup, number)
Hvor:
stmt
er koden hvis utførelsestid vi ønsker å måle. Dette kan være en enkelt linje, flere linjer eller navnet på en funksjon.setup
er koden som kjøres én gang førstmt
. Dette kan være nødvendig for å klargjøre miljøet for kodebiten som skal testes. For eksempel, hvis du tester tiden det tar å lage en NumPy-matrise, er import av NumPy en del avsetup
.number
bestemmer hvor mange gangerstmt
skal kjøres. Standardverdien er 1 000 000, men du kan selv velge en annen verdi.
Nå som vi har sett på syntaksen, la oss se noen eksempler i praksis.
Måling av enkle Python-uttrykk
I dette avsnittet skal vi bruke timeit
for å måle ytelsen til enkle Python-uttrykk.
Start en Python REPL og kjør følgende kode. Vi skal måle tidsbruken for eksponentiering og heltallsdivisjon, med 10 000 og 100 000 repeteringer.
Merk at uttrykkene som skal måles sendes inn som en Python-streng, der semikolon brukes for å skille de forskjellige uttrykkene.
>>> import timeit
>>> timeit.timeit('3**4;3//4',number=10000)
0.0004020999999738706
>>> timeit.timeit('3**4;3//4',number=100000)
0.0013780000000451764
Kjøre Python timeit
fra kommandolinjen
Du kan også bruke timeit
direkte fra kommandolinjen. Kommandoen tilsvarer timeit
-funksjonskallet slik:
$ python -m timeit -n [number] -s [setup] [stmt]
python -m timeit
angir at vi kjørertimeit
som hovedmodul.-n
er en kommando som angir hvor mange ganger koden skal kjøres. Dette tilsvarer parameterennumber
itimeit()
.-s
brukes til å angisetup
-koden.
Her er en ny versjon av forrige eksempel, denne gangen med kommandolinjen:
$ python -m timeit -n 100000 '3**4;3//4'
100000 loops, best of 5: 35.8 nsec per loop
I dette eksemplet måler vi ytelsen til den innebygde len()
-funksjonen. Initialiseringen av strengen er setup
-koden som legges inn med -s
-alternativet.
$ python -m timeit -n 100000 -s "string_1 = 'coding'" 'len(string_1)'
100000 loops, best of 5: 239 nsec per loop
Legg merke til at resultatet viser den beste tiden av 5 kjøringer. Når du kjører timeit
via kommandolinjen er -r
-alternativet (antall repeteringer) satt til standardverdien 5. Det betyr at stmt
kjøres flere ganger, og den beste tiden blir vist.
Analyse av metoder for å snu strenger med timeit
Når du arbeider med strenger i Python, kan du ha behov for å snu dem. De to vanligste metodene for å snu en streng er:
- Bruke streng-slicing
- Bruke
reversed()
-funksjonen ogjoin()
-metoden
Snu Python-strenger ved bruk av streng-slicing
La oss se hvordan streng-slicing fungerer og hvordan du kan bruke det til å snu en streng. Syntaksen en_streng[start:stopp]
returnerer en del av strengen som starter ved start
og går frem til, men ikke inkludert, stopp
-indeksen. La oss se på et eksempel.
Ta for eksempel strengen «Python». Strengen har lengde 6 og indeksene går fra 0, 1, 2 og opp til 5.
>>> string_1 = 'Python'
Når du spesifiserer både start
– og stopp
-verdien, får du en strengbit som går fra start
til stopp
– 1. Derfor vil string_1[1:4]
returnere «yth».
>>> string_1 = 'Python'
>>> string_1[1:4]
'yth'
Dersom du ikke spesifiserer start
-verdien, brukes standardverdien 0. Da starter utsnittet ved indeks 0 og går frem til stopp
– 1.
Her er stopp
-verdien 3, så utsnittet starter ved indeks 0 og går frem til indeks 2.
>>> string_1[:3]
'Pyt'
Hvis du ikke inkluderer stopp
-indeksen, starter utsnittet ved start
-indeksen (1) og går frem til slutten av strengen.
>>> string_1[1:]
'ython'
Hvis du hopper over både start
– og stopp
-verdien, får du hele strengen.
>>> string_1[::]
'Python'
La oss lage et utsnitt med en steg-verdi. Hvis start
, stopp
og steg
-verdiene er henholdsvis 1, 5 og 2, får vi et utsnitt som starter ved 1, går til 4 (ikke inkludert 5) og inkluderer annethvert tegn.
>>> string_1[1:5:2]
'yh'
Med en negativ steg
-verdi, kan du lage et utsnitt som starter på slutten av strengen. Med steg
satt til -2, vil string_1[5:2:-2]
gi følgende utsnitt:
>>> string_1[5:2:-2]
'nh'
For å få en omvendt kopi av strengen hopper vi over start
– og stopp
-verdiene og setter steg
til -1, slik:
>>> string_1[::-1]
'nohtyP'
Oppsummert: streng[::-1]
returnerer en omvendt kopi av strengen.
Snu strenger med innebygde funksjoner og strengmetoder
Den innebygde funksjonen reversed()
i Python returnerer en reversert iterator over elementene i strengen.
>>> string_1 = 'Python'
>>> reversed(string_1)
<reversed object at 0x00BEAF70>
Du kan iterere gjennom den omvendte iteratoren ved hjelp av en for
-løkke:
for char in reversed(string_1):
print(char)
Dette vil gi deg tilgang til elementene i strengen i omvendt rekkefølge.
# Output
n
o
h
t
y
P
Deretter kan du bruke join()
-metoden på den omvendte iteratoren med syntaksen: <sep>.join(reversed(en_streng))
.
Kodebiten under viser et par eksempler der skilletegnet er henholdsvis en bindestrek og et mellomrom.
>>> '-'.join(reversed(string1))
'n-o-h-t-y-P'
>>> ' '.join(reversed(string1))
'n o h t y P'
I dette tilfellet ønsker vi ikke noe skilletegn. Derfor setter vi skilletegnet til en tom streng for å få en omvendt kopi av strengen:
>>> ''.join(reversed(string1))
'nohtyP'
Ved å bruke ''.join(reversed(en_streng))
returneres en reversert kopi av strengen.
Sammenligne kjøretid med timeit
Nå har vi sett to metoder for å reversere en streng. Men hvilken er raskest? La oss finne det ut.
I det tidligere eksemplet der vi målte enkle Python-uttrykk, trengte vi ikke setup
-kode. Men i dette tilfellet snur vi en Python-streng. Selv om snuoperasjonen kjøres det antall ganger som er spesifisert med number
, kjøres initialiseringen av strengen kun én gang.
>>> 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
For samme antall repetisjoner er det å snu strengen ved hjelp av slicing raskere enn å bruke join()
-metoden og reversed()
-funksjonen.
Måling av Python-funksjoner med timeit
I dette avsnittet skal vi se på hvordan man kan måle ytelsen til Python-funksjoner med timeit
-funksjonen. Gitt en liste med strenger, returnerer følgende funksjon en liste over strenger som inneholder minst ett siffer.
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
Vi ønsker å måle tidsbruken til Python-funksjonen hasDigit()
med timeit
.
Først må vi identifisere hva som skal måles, altså stmt
. Det er kallet til funksjonen hasDigit()
med en liste over strenger som argument. Deretter må vi definere setup
-koden. Hva skal denne bestå av?
For at funksjonskallet skal fungere må setup
-koden inneholde:
- Definisjonen av funksjonen
hasDigit()
- Initialiseringen av argumentlisten med strenger
La oss definere setup
-koden i en string, slik:
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']
"""
Nå kan vi bruke timeit
-funksjonen og få tidsbruken for hasDigit()
-funksjonen for 100 000 repetisjoner.
import timeit
timeit.timeit('hasDigit(thislist)',setup=setup,number=100000)
# Output
0.2810094920000097
Konklusjon
Du har lært hvordan du kan bruke Pythons timeit
-funksjon for å måle tidsbruken til uttrykk, funksjoner og andre objekter som kan kalles. Dette kan være nyttig for å teste koden din, sammenligne ytelser av ulike metoder for det samme, og mer.
La oss oppsummere hva vi har gått gjennom i denne veiledningen. Du kan bruke timeit()
-funksjonen med syntaksen timeit.timeit(stmt=...,setup=...,number=...)
. Alternativt kan du kjøre timeit
fra kommandolinjen for å måle ytelsen til korte kodebiter.
Som et neste steg kan du utforske andre Python-profileringsverktøy som line-profiler
og mem-profiler
for å analysere koden din for henholdsvis tidsbruk og minnebruk.
Til slutt, lærer du hvordan du kan beregne tidsforskjeller i Python.