Domanda

Come può un iteratore su una sequenza non vuota, senza filtraggio e senza aggregazione (sum(), ecc), resa nulla?

Si consideri un semplice esempio:

sequence = ['a', 'b', 'c']
list((el, ord(el)) for el in sequence)

Questo produce [('a', 97), ('b', 98), ('c', 99)] come previsto.

Ora, basta scambiare la ord(el) fuori per un'espressione che prende il primo valore di qualche generatore utilizzando (...).next() - perdonare l'esempio inventato:

def odd_integers_up_to_length(str):
    return (x for x in xrange(len(str)) if x%2==1)

list((el, odd_integers_up_to_length(el).next()) for el in sequence)

Questo produce []. Sì, lista vuota. Nessun tuple ('a',stuff). Niente.

Ma non stiamo filtrando o aggregazione o la riduzione. Un generatore di espressione sopra n oggetti senza filtrazione o aggregazione deve cedere oggetti n, giusto? Cosa sta succedendo?

È stato utile?

Soluzione

odd_integers_up_to_length(el).next() alzerà StopIteration, che non è catturato lì, ma viene catturato per il generatore di espressione all'interno di esso, fermandosi senza mai cedere nulla.

sguardo alla prima iterazione, quando il valore è 'a':

>>> odd_integers_up_to_length('a').next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Altri suggerimenti

Succede che la chiamata next() solleva un'eccezione StopIteration che si propaga la pila all'espressione generatore esterno e ferma che iterazione.

Una StopIteration è il modo normale per un iteratore per segnalare che il gioco è fatto. Generalmente non vediamo, perché in genere la chiamata next() avviene all'interno di un costrutto che consuma l'iteratore, ad esempio for x in iterator o sum(iterator). Ma quando chiamiamo direttamente next(), noi siamo i responsabili per prendere il StopIteration. Non farlo scaturisce una perdita nel astrazione, che qui porta a un comportamento imprevisto nell'iterazione esterno.

La lezione, suppongo: attenzione sulle chiamate senza scalo a next()

.

str è una parola chiave riservata, è necessario denominare la variabile in modo diverso

Sono stato anche di consigliare circa il prossimo

>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]

Quindi non è list dando problemi qui ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top