Finally figured out member generators...

Bjorn Pettersen BPettersen at NAREX.com
Mon Mar 3 14:23:45 EST 2003


In case anyone else has struggled to make their class iterable by making
a generator produce the individual items...

Here's the doc-report I filed:
This should probably go at the end of 2.2.5 (LibRef).

"""If you are designing a class that should be iterable, i.e. you want
to be able to say "for x in myClass:...", and, you also want the
convenience of using a member function that is a generator to provide
the items, your class' __iter__() method should return
"MyClass.myGenerator(self)". The object returned from this call is an
iterator-generator that implements both of the required __iter__() and
next() methods.

Example:
   class Range10:
       def __init__(self): self.scale = 5
       def __iter__(self):
           return Range10.generateItems(self)
       def generateItems(self):
           for i in range(10): yield i * self.scale

There are a couple of subtleties here. First, only "user-defined
functions" are converted to methods when accessed through a class or
instance, i.e.myObject.foo() will extract the foo function wrap it up as
a method object, insert myObject in the argument list and call it
(LibRef: 3.2/Callable types/User-defined methods). [thanks to Alex M.
for clarifying this issue for me]

This automatic conversion does not happen for any other type of objects
defined inside class scope. In our case, generateItems() will be a
generator-iterator, i.e. not a "user-defined function". Thus the
conversion to an instance method does not happen, and it is left as a
static method of the class. [this seems like it might be a bug to
me...].

To get around this irregularity, make sure your __iter__() calls
generateItems() as a static method, and explictly pass self.
"""

-- bjorn





More information about the Python-list mailing list