2012-03-26 19 views
7

Eventuali duplicati:
The Python yield keyword explainedCosa fa yield in python 2.7?

Okay, ho probabilmente formulato la questione male, ma questa è la situazione che ho.

ho questa riga di codice in Python 2.7, che sto cercando di capire:

yield (padding_zeros + number_string).encode("ascii") 

In questa riga di codice, padding_zeros è una stringa di un numero variabile di '0 e number_string è un numero sotto forma di stringa che può essere qualsiasi numero compreso tra 0 e 10000.

Sono abbastanza sicuro che lo .encode("ascii") converta solo l'output di rendimento in ascii.

Quello che mi interessa completamente è ciò che fa lo yield (padding_zeros + number_string).

So che avvia un generatore ma ho passato un sacco di tempo a cercare online e a leggere la sintassi, ma non riesco ancora a capire quale sia il vero generatore . Non aiuta che questa sia la mia prima volta a guardare Python (il mio obiettivo ultimo è quello di convertire questo codice in C#).

Quindi, in sostanza, per favore qualcuno potrebbe spiegarmi cosa fa questa riga di codice? Aggiunge semplicemente le due stringhe o fa qualcosa di un po 'più complicato?

Per ulteriori contesto, questo è il blocco che quella riga di codice appare in:

for current_length in range(4, max_length + 1): 
    for i in range(0, pow(10, current_length)): 
     number_string = str(i) 
     padding_zeros = "0" * (current_length - len(number_string)) 
     yield (padding_zeros + number_string).encode("ascii") 

(max_length essere esattamente quello che sembra - un numero che indica la lunghezza massima di qualcosa)

Grazie in anticipo per qualsiasi e tutte le risposte (anche se mi stanno dicendo di non essere un noob fremente) :)

EDIT: Grazie mille per le risposte - anche se ho potuto solo p ciao come la migliore risposta sono stati tutti molto utili. E grazie anche per i commenti - come alcuni hanno sottolineato, What does the "yield" keyword do in Python? è un'ottima guida generale per generare, generatori e iterazioni anche se non ho trovato una risposta alla mia situazione specifica :)

+0

È questo il Python 2 o Python 3? –

+0

Ciao George, la tua domanda è stata esaudita qui abbastanza bene, mi sento: http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained – MattH

+0

Vedi questa risposta: http://stackoverflow.com/questions/231767/the-python-yield-keyword-explain/231855 # 231855 –

risposta

6

OK, sai di generatori, in modo che la parte yield bisogno di spiegazioni . Belle.

Quindi cosa fa effettivamente quella linea? Non molto:

Si concatena padding_zeros e number_string e quindi codifica il risultato in ASCII. Che in Python 2.7 è un no-op perché la stringa è ASCII per cominciare (è composta solo da cifre ASCII, per definizione).

In Python 3, sarebbe diverso; qui lo .encode() avrebbe convertito la stringa in un oggetto bytes. Ma in Python 2, non ha alcun senso.

+0

Grazie - potrebbe essere che questo codice sia stato originariamente scritto in Python 3 che spiegherebbe perché appare come un non operativo in Python 2. Non può essere sicuro al 100%. Grazie per la tua risposta e scusa per essere stato così incapace. – GeorgePotter

1

In questo Il caso yield viene utilizzato per eseguire la valutazione lazy. I prossimi codici sono più o meno equivalenti:

def f(...): 
    for current_length in range(4, max_length + 1): 
     for i in range(0, pow(10, current_length)): 
      number_string = str(i) 
      padding_zeros = "0" * (current_length - len(number_string)) 
      yield (padding_zeros + number_string).encode("ascii") 

result = list(f()) 

contro

def f(...): 
    result = list() 
    for current_length in range(4, max_length + 1): 
     for i in range(0, pow(10, current_length)): 
      number_string = str(i) 
      padding_zeros = "0" * (current_length - len(number_string)) 
      result.append((padding_zeros + number_string).encode("ascii")) 
    return result 

result = f() 

Si può solo seguire la seconda in voi di traduzione codice.

+1

Tranne che la seconda versione restituisce una lista, mentre il generatore produrrà ogni elemento uno per uno. – Marcin

+0

Grazie mille :) – GeorgePotter

+0

@Marcin sicuro. Ma non penso che l'OP se ne preoccupi :) –

3

yield è come il ritorno in un generatore.

Nel punto in cui viene eseguito il yield, l'esecuzione della funzione di generatore si interrompe e il valore viene restituito.La differenza è che quando il generatore viene richiamato di nuovo, l'esecuzione viene riavviata all'istruzione yield e continua fino a quando non viene raggiunto un altro rendimento o viene sollevata un'eccezione (non gestita) o viene colpito un numero return. Lo return o eccezione terminerà il generatore.

Il punto di un generatore è che è possibile richiamarlo come x = next(generator) o x = generator.next() e ogni volta che si riceverà il valore dal rendimento all'interno del generatore. I generatori sono anche iterabili, quindi possono essere utilizzati come origine di un loop: for x in generator: print x.

Come in C#, l'operatore . richiama il metodo denominato alla sua destra sull'oggetto che appare sulla sinistra dell'operatore. Di conseguenza, (padding_zeros + number_string).encode("ascii") chiama encode sul risultato di (padding_zeros + number_string).

Per il significato di encode, vedere qui: http://docs.python.org/library/stdtypes.html#str.encode

per il riferimento di lingua (supponendo che si sta utilizzando Python 2): http://docs.python.org/reference/index.html

+1

Grazie mille :) – GeorgePotter

+0

@GeorgePotter Nessun problema. Sentiti libero di accettare una risposta e vota tutti gli altri che ritieni utili (una volta che hai potuto votare). – Marcin

0

un generatore è una statemachine che implementa l'interfaccia iteratore o __iter__ in python. attenderà dopo "resa" fino a quando non si chiama next() su di esso.

provare questo:

def my_gen(): 
    for current_length in range(4, max_length + 1): 
     for i in range(0, pow(10, current_length)): 
      number_string = str(i) 
      padding_zeros = "0" * (current_length - len(number_string)) 
      print "generate %s" % i 
      yield (padding_zeros + number_string).encode("ascii") 

for i in my_gen(): 
    print "iterate %s" % i 
+0

Un generatore non è una statostatrice -1: http://en.wikipedia.org/wiki/Finite-state_machine. Inoltre, l'interfaccia del generatore principale è 'next'. – Marcin

+0

penso che sia (un abbastanza semplice): ogni chiamata a next() cambia il suo stato, che gli permette di andare avanti o di fermarsi. (Ho modificato il secondo '__iter__' a 'next()') –

+0

Questa non è la definizione di una statemachine. – Marcin