Generator - Misunderstood python yield

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

This code below works correct :

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>
 
gen_line.next() #  <html> 
  
gen_line.next() # ... next line in file 

But this function raises StopIteration. I don t understand why ?

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

gen_line = file_gen( foo.html )
gen_line.next()  #  <!DOCTYPE>
 
gen_line.next()  # StopIteration

Answers

You have:

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

Notice line = f.readline() This only reads 1 line from the file.

Compare:

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

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

with this:

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 can only be called once with a particular object or expression. Once it is used by the receiver it must be regenerated. So you need a loop around reading each line of the file.

You can use your second (less readable) form this way:

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

You need a loop to create the the items to yield. In your first case, for line in f: yield line is a loop.

I would rewrite your function this way:

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

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/19981355/misunderstood-python-yield

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils