On Tue, May 27, 2014 at 12:27 PM, Degreat Yartey
<yarteydegre...@gmail.com> wrote:
> I am studying python on my own (i.e. i am between the beginner and
> intermediate level) and i haven't met any difficulty until i reached the
> topic 'Generators and Iterators'.
> I need an explanation so simple as using the expression 'print ()', in this
> case 'yield'.
> Python 2.6 here!
> Thank you.
>

Simply put, a generator is just like a function - except that a
function returns a value and then dies, but a generator yields a value
and sticks around, waiting to yield another one - and another, and
another, etc.

I had some difficulty grasping the concept of generators at first
because the examples you get in the tutorials are either trivial (you
could do the same thing some other way, and it would be simpler) or
horribly complex (and you get bogged down in the problem, rather than
getting to grips with generators themselves.)

So here's a real-life example - the first time I actually used
generators... and they actually saved me a LOT of hard work and
confusion.  I needed to read some database files (from a very old
database, for which I don't have an API - so I basically needed to
read each record and interpret it byte-by-byte).  I wrote a bunch of
classes for the different tables in the database (I'll use Patient()
as my example), but the heart of the operation is a generator.


def RecordGenerator(office=None, fileType=None):
    obj = fTypes[fileType]()    # create an empty record so we can
read its attributes
    recLen = obj.RecordLength    # such as the record length, the filename, etc.
    with open(getattr(office, obj.TLA) + '.dat','rb') as inFile:
        tmpIn = inFile.read()
        buf = StringIO.StringIO(tmpIn)
        inRec = buf.read(recLen)    # initialize inRec and burn the
header record
        while not (len(inRec) < recLen):
            inRec = buf.read(recLen)
            obj = fTypes[fileType](inRec)
            if (obj.Valid):
                yield obj
        buf.close()

Now I'm writing a program that needs to process all the patients in
office 01.  I write the following:

for obj in RecordGenerator(01, "Patient"):
    doStuffPart1
    doStuffPart2
    doStuffPart3
    etc.

The generator creates an empty Patient() object, looks at its
attributes, and finds that the filename is "01PAT.dat" and the records
are 1024 bytes long.  It opens the file and reads it into tmpIn, then
grabs 1024-byte chunks of tmpIn and passes them to Patient() until it
finds a valid (not deleted, not corrupted) patient record.  It
"yields" that record to the caller, and waits.
When "doStuffPart3" has completed, I go back to the top of the "for"
loop and ask for the next patient.  RecordGenerator steps through
tmpIn, 1024 bytes at a time, until it finds a valid patient, then
yields it and waits.  When it hits the end of the file (or, more
precisely, when the remaining length of tmpIn is less than a full
record length), it quits.

Essentially, you write a generator as if it were a function - but you
use it as if it were a sequence.  Best of both worlds, baby!
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to