Utilizzo di Python Timeit per cronometrare il codice

In questo tutorial imparerai come utilizzare la funzione timeit dal modulo timeit di Python. Imparerai come cronometrare semplici espressioni e funzioni in Python.

La tempistica del codice può aiutarti a ottenere una stima del tempo di esecuzione di un pezzo di codice e anche a identificare le sezioni del codice che devono essere ottimizzate.

Inizieremo imparando la sintassi della funzione timeit di Python. E poi codificheremo esempi per capire come usarlo per cronometrare blocchi di codice e funzioni nel tuo modulo Python. Cominciamo.

Come usare la funzione timeit di Python

Il modulo timeit fa parte della libreria standard di Python e puoi importarlo:

import timeit

La sintassi per utilizzare la funzione timeit dal modulo timeit è la seguente:

timeit.timeit(stmt, setup, number)

Qui:

  • stmt è il pezzo di codice il cui tempo di esecuzione deve essere misurato. Puoi specificarlo come una semplice stringa Python o una stringa multilinea o passare il nome del chiamabile.
  • Come suggerisce il nome, setup denota la parte di codice che deve essere eseguita solo una volta, spesso come prerequisito per l’esecuzione di stmt. Ad esempio, supponi di calcolare il tempo di esecuzione per la creazione di un array NumPy. In questo caso, l’importazione di numpy è il codice di installazione e la creazione effettiva è l’istruzione da cronometrare.
  • Il numero del parametro indica il numero di volte in cui stmt viene eseguito. Il valore predefinito di number è 1 milione (1000000), ma puoi anche impostare questo parametro su qualsiasi altro valore di tua scelta.

Ora che abbiamo imparato la sintassi per utilizzare la funzione timeit(), iniziamo a codificare alcuni esempi.

Sincronizzazione di semplici espressioni Python

In questa sezione proveremo a misurare il tempo di esecuzione di semplici espressioni Python usando timeit.

Avvia un REPL Python ed esegui i seguenti esempi di codice. Qui calcoliamo il tempo di esecuzione delle operazioni di esponenziazione e divisione del pavimento per 10000 e 100000 esecuzioni.

Si noti che passiamo l’istruzione da cronometrare come una stringa Python e usiamo un punto e virgola per separare le diverse espressioni nell’istruzione.

>>> import timeit
>>> timeit.timeit('3**4;3//4',number=10000)
0.0004020999999738706

>>> timeit.timeit('3**4;3//4',number=100000)
0.0013780000000451764

Esecuzione di Python timeit dalla riga di comando

Puoi anche usare timeit dalla riga di comando. Ecco l’equivalente da riga di comando della chiamata alla funzione timeit:

$ python-m timeit -n [number] -s [setup] [stmt]
  • python -m timeit rappresenta che eseguiamo timeit come modulo principale.
  • n è un’opzione della riga di comando che indica il numero di volte in cui il codice deve essere eseguito. Questo è equivalente all’argomento numero nella chiamata alla funzione timeit().
  • È possibile utilizzare l’opzione -s per definire il codice di installazione.

Qui, riscriviamo l’esempio precedente usando l’equivalente della riga di comando:

$ python -m timeit -n 100000 '3**4;3//4'
100000 loops, best of 5: 35.8 nsec per loop

In questo esempio, calcoliamo il tempo di esecuzione della funzione incorporata len(). L’inizializzazione della stringa è il codice di configurazione passato utilizzando l’opzione s.

$ python -m timeit -n 100000 -s "string_1 = 'coding'" 'len(string_1)'
100000 loops, best of 5: 239 nsec per loop

Nell’output, si noti che otteniamo il tempo di esecuzione al meglio di 5 esecuzioni. Cosa significa questo? Quando si esegue timeit dalla riga di comando, l’opzione di ripetizione r viene impostata sul valore predefinito 5. Ciò significa che l’esecuzione di stmt per il numero di volte specificato viene ripetuta cinque volte e viene restituito il migliore dei tempi di esecuzione.

Analisi dei metodi di inversione di stringhe utilizzando timeit

Quando lavori con le stringhe Python, potresti volerle invertire. I due approcci più comuni all’inversione di stringa sono i seguenti:

  • Usando lo string slicing
  • Utilizzando la funzione reversed() e il metodo join()

Inverti le stringhe Python usando il taglio delle stringhe

Esaminiamo come funziona l’affettamento delle stringhe e come puoi usarlo per invertire una stringa Python. Usando la sintassi qualche-stringa[start:stop] restituisce una sezione della stringa che inizia dall’inizio dell’indice e si estende fino all’arresto dell’indice-1. Facciamo un esempio.

Considera la seguente stringa ‘Python’. La stringa è di lunghezza 6 e l’elenco degli indici è 0, 1, 2 fino a 5.

>>> string_1 = 'Python'

Quando si specificano entrambi i valori start e stop, si ottiene una porzione di stringa che si estende da start a stop-1. Pertanto, string_1[1:4] restituisce ‘yth’.

>>> string_1 = 'Python'
>>> string_1[1:4]
'yth'

Quando non si specifica il valore iniziale, viene utilizzato il valore iniziale predefinito pari a zero e la sezione inizia dall’indice zero e si estende fino all’arresto – 1.

Qui, il valore di stop è 3, quindi la fetta inizia dall’indice 0 e sale fino all’indice 2.

>>> string_1[:3]
'Pyt'

Quando non includi l’indice di stop, vedi che la sezione inizia dall’indice di inizio (1) e si estende fino alla fine della stringa.

>>> string_1[1:]
'ython'

Ignorando entrambi i valori start e stop restituisce una porzione dell’intera stringa.

>>> string_1[::]
'Python'

Creiamo una sezione con il valore del passo. Impostare i valori di avvio, arresto e incremento rispettivamente su 1, 5 e 2. Otteniamo una porzione della stringa che parte da 1 e si estende fino a 4 (escluso il punto finale 5) contenente ogni secondo carattere.

>>> string_1[1:5:2]
'yh'

Quando usi un passo negativo, puoi ottenere una fetta che inizia alla fine della stringa. Con il passo impostato su -2, string_1[5:2:-2] dà la seguente fetta:

>>> string_1[5:2:-2]
'nh'

Quindi, per ottenere una copia invertita della stringa, saltiamo i valori start e stop e impostiamo il passo su -1, come mostrato:

>>> string_1[::-1]
'nohtyP'

In sintesi: stringa[::-1] restituisce una copia invertita della stringa.

Inversione di stringhe utilizzando funzioni incorporate e metodi di stringa

La funzione incorporata reversed() in Python restituirà un iteratore inverso sugli elementi della stringa.

>>> string_1 = 'Python'
>>> reversed(string_1)
<reversed object at 0x00BEAF70>

Quindi puoi scorrere l’iteratore inverso usando un ciclo for:

for char in reversed(string_1):
    print(char)

E accedi agli elementi della stringa nell’ordine inverso.

# Output
n
o
h
t
y
P

Successivamente, puoi chiamare il metodo join() sull’iteratore inverso con la sintassi: .join(reversed(some-string)).

Il frammento di codice seguente mostra un paio di esempi in cui il separatore è rispettivamente un trattino e uno spazio bianco.

>>> '-'.join(reversed(string1))
'n-o-h-t-y-P'
>>> ' '.join(reversed(string1))
'n o h t y P'

Qui non vogliamo alcun separatore; quindi imposta il separatore su una stringa vuota per ottenere una copia invertita della stringa:

>>> ''.join(reversed(string1))
'nohtyP'

L’utilizzo di .join(reversed(some-string)) restituisce una copia invertita della stringa.

Confronto dei tempi di esecuzione Utilizzo di timeit

Finora abbiamo imparato due approcci per invertire le stringhe Python. Ma quale di loro è più veloce? Scopriamolo.

In un esempio precedente in cui abbiamo cronometrato semplici espressioni Python, non avevamo alcun codice di configurazione. Qui stiamo invertendo la stringa Python. Mentre l’operazione di inversione della stringa viene eseguita per il numero di volte specificato da number, il codice di installazione è l’inizializzazione della stringa che verrà eseguita solo una volta.

>>> 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

Per lo stesso numero di esecuzioni per invertire la stringa data, l’approccio di slicing della stringa è più veloce rispetto all’utilizzo del metodo join() e della funzione reversed().

Funzioni Python di cronometraggio Utilizzo di timeit

In questa sezione, impariamo come cronometrare le funzioni Python con la funzione timeit. Dato un elenco di stringhe, la seguente funzione hasDigit restituisce l’elenco di stringhe che hanno almeno una cifra.

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

Ora vorremmo misurare il tempo di esecuzione di questa funzione Python hasDigit() usando timeit.

Identifichiamo prima l’istruzione da cronometrare (stmt). È la chiamata alla funzione hasDigit() con un elenco di stringhe come argomento. Successivamente, definiamo il codice di installazione. Riesci a indovinare quale dovrebbe essere il codice di installazione?

Affinché la chiamata di funzione venga eseguita correttamente, il codice di installazione deve includere quanto segue:

  • La definizione della funzione hasDigit()
  • L’inizializzazione dell’elenco di stringhe di argomenti

Definiamo il codice di configurazione nella stringa di configurazione, come mostrato di seguito:

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']
     """

Successivamente, possiamo utilizzare la funzione timeit e ottenere il tempo di esecuzione della funzione hasDigit() per 100000 esecuzioni.

import timeit
timeit.timeit('hasDigit(thislist)',setup=setup,number=100000)
# Output
0.2810094920000097

Conclusione

Hai imparato come usare la funzione timeit di Python per cronometrare espressioni, funzioni e altri callable. Questo può aiutarti a confrontare il tuo codice, confrontare i tempi di esecuzione di diverse implementazioni della stessa funzione e altro ancora.

Rivediamo ciò che abbiamo imparato in questo tutorial. È possibile utilizzare la funzione timeit() con la sintassi timeit.timeit(stmt=…,setup=…,number=…). In alternativa, puoi eseguire timeit dalla riga di comando per cronometrare frammenti di codice breve.

Come passaggio successivo, puoi esplorare come utilizzare altri pacchetti di profilatura Python come line-profiler e memprofiler per profilare il tuo codice rispettivamente per tempo e memoria.

Successivamente, scopri come calcolare la differenza di fuso orario in Python.