2010-09-06 3 views
5

io sono un collezionista e ho nido rookie per i loop quando scrivo pitone, in questo modo:Python: cicli for innestati o "next" dichiarazione

dict = { 
    key1: {subkey/value1: value2} 
    ... 
    keyn: {subkeyn/valuen: valuen+1} 
    } 

for key in dict: 
    for subkey/value in key: 
     do it to it 

Sono a conoscenza di una parola chiave "next" che raggiungerebbe lo stesso obiettivo in una riga (ho fatto una domanda su come usarlo ma non l'ho capito bene).

Quindi, per me, un ciclo annidato è molto più leggibile. Perché, allora le persone usano "next"? Ho letto da qualche parte che Python è un linguaggio tipizzato dinamicamente e interpretato e poiché entrambi concatenano numeri di stringhe e somme, che deve controllare i tipi di variabili per ogni iterazione del ciclo per sapere quali sono gli operatori, ecc. L'uso di "next" previene questo in qualche modo, velocizzando l'esecuzione o è solo una questione di stile/preferenza?

risposta

20

next è prezioso per far avanzare un iteratore quando necessario, senza che l'avanzamento controllo di un esplicito for loop. Ad esempio, se si desidera "il primo elemento in S che è maggiore di 100", next(x for x in S if x > 100) lo darà a te, senza muss, senza problemi, senza lavoro non necessario (dato che tutto termina non appena si trova un idoneo x) - e si ottiene un'eccezione (StopIteration) se inaspettatamente no x corrisponde alla condizione. Se è prevista una mancata corrispondenza e si desidera None in questo caso, lo consegnerà next((x for x in S if x > 100), None). Per questo scopo specifico, potrebbe essere più chiaro se next fosse effettivamente denominato first, ma che tradirebbe il suo uso molto più generale.

Considerare, ad esempio, l'operazione di unire più sequenze (ad es. Unione o intersezione di sequenze ordinate, ad esempio file ordinati, in cui gli elementi sono linee). Ancora una volta, next è proprio quello che il medico ha ordinato, perché nessuna delle sequenze può dominare sugli altri controllando un "ciclo principale for". Quindi, supponendo che per semplicità non possano esistere duplicati (una condizione che non è difficile da rilassare se necessario), si mantengono le coppiein un elenco controllato da heapq, e la fusione diventa facile ... ma solo grazie alla magia di next per avanzare il corregge il file una volta che il suo oggetto è stato usato e solo quel file.

import heapq 

def merge(*theopentextfiles): 
    theheap = [] 
    for afile in theopentextfiles: 
     theitem = next(afile, '') 
     if theitem: theheap.append((theitem, afile)) 
    heapq.heapify(theheap) 
    while theheap: 
     theitem, afile = heapq.heappop(theheap) 
     yielf theitem 
     theitem = next(afile, '') 
     if theitem: heapq.heappush(theheap, (theitem, afile)) 

Basta cercare di fare qualsiasi cosa ovunque questo elegante senza next ... -!)

Si potrebbe andare avanti per molto tempo, ma i due casi d'uso "avanzano un iteratore di un posto (senza lasciarlo controllare un intero ciclo for) "e" ottenere solo il primo elemento da un account iteratore "per gli usi più importanti di next.

+0

+1 Bella risposta! –

+0

@ AJ, grazie! –

+0

+1 L'hai fatto di nuovo. Mi sono appena reso conto che il mio utile qualsiasi aka prima poteva essere definito (prima non False in qualsiasi sequenza o ultimo valore in sequenza se tutti sono False) potrebbe essere definito anche con next e iter. –