Skip to content

Iteratori infiniti in Python (itertools.count, cycle, repeat)

Python

In Python, le funzioni itertools.count(), itertools.cycle() e itertools.repeat() nel modulo itertools della libreria standard possono essere utilizzate per creare iteratori infiniti.

In questo articolo vengono descritti i seguenti contenuti.

  • Conta all’infinito:itertools.count()
  • Ciclo elementi di un iterabile indefinitamente:itertools.cycle()
  • Ripetere lo stesso valore all’infinito:itertools.repeat()

Per ogni funzione vengono presentati esempi di processo iterativo con l’istruzione per e una combinazione con la funzione zip().

Vedere gli articoli seguenti per ulteriori informazioni sull’istruzione per e sulla funzione zip().

Se li usi nell’istruzione per, fai attenzione a specificare la condizione finale e l’interruzione; in caso contrario, il codice finirà in un ciclo infinito.

Cicli infiniti con contatori, ecc. possono essere implementati con l’istruzione mentre, ma spesso è più facile scriverli usando le funzioni itertools.

itertools.count() crea un iteratore che produce valori che conta avanti o indietro all’infinito.

Per configurazione predefinita, inizia da 0 e aumenta di 1.

import itertools

for i in itertools.count():
    print(i)
    if i > 3:
        break
# 0
# 1
# 2
# 3
# 4

È possibile specificare il valore iniziale con il primo argomento start e l’incremento con il secondo argomento step.

for i in itertools.count(2):
    print(i)
    if i > 3:
        break
# 2
# 3
# 4

for i in itertools.count(step=3):
    print(i)
    if i > 8:
        break
# 0
# 3
# 6
# 9

for i in itertools.count(2, 3):
    print(i)
    if i > 8:
        break
# 2
# 5
# 8
# 11

Se si desidera eseguire il conto alla rovescia, è possibile specificare un valore negativo per il passaggio.

for i in itertools.count(10, -1):
    print(i)
    if i < 8:
        break
# 10
# 9
# 8
# 7

È possibile specificarlo come numero a virgola mobile float, ma in alcuni casi potrebbe essere più accurato utilizzare la moltiplicazione.

Quando si conta con numeri in virgola mobile, a volte è possibile ottenere una migliore precisione sostituendo il codice moltiplicativo come:(start + step * i for i in count()).
itertools.count() — Functions creating iterators for efficient looping — Python 3.9.7 documentation

for i in itertools.count(0.1, 1.5):
    print(i)
    if i > 3:
        break
# 0.1
# 1.6
# 3.1

for i in itertools.count():
    ii = 0.1 + 1.5 * i
    print(ii)
    if ii > 3:
        break
# 0.1
# 1.6
# 3.1

Se combinato con zip(), è possibile creare tuple con contatore.

l1 = ['a', 'b', 'c']
l2 = ['x', 'y', 'z']

print(list(zip(itertools.count(), l1, l2)))
# [(0, 'a', 'x'), (1, 'b', 'y'), (2, 'c', 'z')]

Nota che se usi enumerate() e zip(), vengono create tuple nidificate.

print(list(enumerate(zip(l1, l2))))
# [(0, ('a', 'x')), (1, ('b', 'y')), (2, ('c', 'z'))]

Se lo usi nel ciclo per, puoi anche usare enumerate() e zip() per estrarre ogni valore come segue.

names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]

for i, (name, age) in enumerate(zip(names, ages)):
    print(i, name, age)
# 0 Alice 24
# 1 Bob 50
# 2 Charlie 18

itertools.cycle() crea un iteratore che scorre all’infinito gli elementi di un oggetto iterabile come un elenco.

l = [1, 10, 100]

sum_value = 0

for i in itertools.cycle(l):
    print(i)
    sum_value += i
    if sum_value > 300:
        break
# 1
# 10
# 100
# 1
# 10
# 100
# 1
# 10
# 100

Esempio di specifica di range():

sum_value = 0

for i in itertools.cycle(range(3)):
    print(i)
    sum_value += i
    if sum_value > 5:
        break
# 0
# 1
# 2
# 0
# 1
# 2

Esempio di combinazione con zip():

l1 = [1, 10, 100]
l2 = [0, 1, 2, 3, 4, 5, 6]

print(list(zip(itertools.cycle(l1), l2)))
# [(1, 0), (10, 1), (100, 2), (1, 3), (10, 4), (100, 5), (1, 6)]

itertools.cycle() salva una copia dell’oggetto iterabile originale. Si noti che se la dimensione dell’oggetto iterabile è grande, potrebbe utilizzare memoria.

Nota, questo membro del toolkit potrebbe richiedere una notevole memoria ausiliaria (a seconda della lunghezza dell’iterabile).
itertools.cycle() — Funzioni che creano iteratori per cicli efficienti — Documentazione Python 3.9.7

itertools.repeat() crea un iteratore che restituisce lo stesso valore all’infinito.

sum_value = 0

for i in itertools.repeat(10):
    print(i)
    sum_value += i
    if sum_value > 40:
        break
# 10
# 10
# 10
# 10
# 10

Il numero di iterazioni può essere specificato con il secondo argomento volte.

for i in itertools.repeat(10, 3):
    print(i)
# 10
# 10
# 10

Il primo argomento può essere qualsiasi oggetto. È anche possibile ripetere un oggetto funzione. Nell’esempio seguente viene ripetuta la funzione incorporata len().

for l in itertools.repeat([0, 1, 2], 3):
    print(l)
# [0, 1, 2]
# [0, 1, 2]
# [0, 1, 2]

for func in itertools.repeat(len, 3):
    print(func('abc'))
# 3
# 3
# 3

Esempio di combinazione con zip() è il seguente. Puoi aggiungere elementi costanti.

l = [0, 1, 2, 3]

print(list(zip(itertools.repeat(10), l)))
# [(10, 0), (10, 1), (10, 2), (10, 3)]