2013-11-14 10 views
6

Questo codice di seguito funziona correttamente:Misunderstood pitone resa

def file_gen(f_name): 
    f = open(f_name) 
    for line in f: 
     yield line 

gen_line = file_gen("foo.html") 
gen_line.next() # '<!DOCTYPE>\n' 
gen_line.next() # '<html> \n' 
gen_line.next() # ... next line in file 

Ma questa funzione solleva StopIteration. Non capisco perché?

def file_gen(f_name): 
    f = open(f_name) 
    line = f.readline() 
    yield line 

gen_line = file_gen('foo.html') 
gen_line.next() # '<!DOCTYPE>\n' 
gen_line.next() # StopIteration 
+5

Cosa ti aspetti che accada? – delnan

+3

Il secondo è in realtà un errore di sintassi in Python (non è possibile rientrare nella riga 'yield') – 6502

+0

@ 6502 scusa, ho corretto –

risposta

4

Hai:

def file_gen(f_name): 
    f = open(f_name) 
    line = f.readline() 
    yield line 

Avviso line = f.readline() Questa legge solo 1 riga dal file.

Compare:

def g(x): 
    li=range(x) 
    yield li.pop() 

print list(g(10)) 
# [9] 

con questo:

def g(x): 
    li=range(x) 
    while li: 
     yield li.pop() 

print list(g(10)) 
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 

yield può essere chiamato solo una volta con un oggetto o un'espressione particolare. Una volta utilizzato dal ricevitore, deve essere rigenerato. Quindi è necessario un ciclo di lettura di ogni riga del file.

È possibile utilizzare il secondo (meno leggibile) formano in questo modo:

def file_gen(f_name): 
    f = open(f_name) 
    while True: 
     line = f.readline() 
     if not line: 
      break 
     yield line 

È necessario un ciclo per creare le voci di cedere. Nel primo caso, for line in f: yield line è un loop.

vorrei riscrivere la funzione in questo modo:

def file_gen(f_name): 
    with open(f_name) as f: 
     for line in f: 
      yield line 
+0

thx, ma non capisco cosa c'è di sbagliato nella mia forma? –

+1

@ A.M.Sultanov: Perché 'line = f.readline()' legge solo 1 riga. È necessario avvolgerlo in una qualche forma di ciclo - un ciclo 'while' di un ciclo' for' più leggibile – dawg

+0

@darwig thx, ho capito) –

1

non

line = f.readline() 

solo dare una linea a cedere? quindi l'iterazione si ferma dopo che ...

+0

ma se si utilizza questo modulo: file = open ('foo.html') file.readline() file.readline() ... non si ferma sulla seconda riga –

+0

Quando provo, mi dà solo la seconda riga anziché la prima, quindi interrompe l'iterazione sulle successive chiamate next(), come mi aspetterei. Ad ogni modo, sembra che tu abbia toccato il fondo del tuo problema ... – gonkan

2

Si ottiene StopIteration sul secondo successivo() perché hai generato solo un risultato. Volevi farlo invece?

def file_gen(f_name): 
    f = open(f_name) 
    lines = f.readlines() 
    for line in lines: 
     yield line