[Python-bugs-list] [ python-Bugs-696777 ] How to make a class iterable using a member generator.
SourceForge.net
noreply@sourceforge.net
Wed, 25 Jun 2003 12:04:43 -0700
Bugs item #696777, was opened at 2003-03-03 14:17
Message generated for change (Comment added) made by rhettinger
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=696777&group_id=5470
Category: Documentation
Group: Python 2.2.2
>Status: Closed
>Resolution: Fixed
Priority: 5
Submitted By: Bjorn Pettersen (bpettersen)
Assigned to: Raymond Hettinger (rhettinger)
Summary: How to make a class iterable using a member generator.
Initial Comment:
This should probably go at the end of 2.2.5 (LibRef). [I
was trying all possible variations of __iter__ returning
self, with next() as a method...]
"""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 "self.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
passes self.
"""
-- bjorn
----------------------------------------------------------------------
>Comment By: Raymond Hettinger (rhettinger)
Date: 2003-06-25 14:04
Message:
Logged In: YES
user_id=80475
Expanded the docs as requested (though much more tersely
worded). See Doc/lib/libstdtypes.tex 1.128.
----------------------------------------------------------------------
Comment By: Terry J. Reedy (tjreedy)
Date: 2003-03-09 12:57
Message:
Logged In: YES
user_id=593130
As others have posted (with examples) on both c.l.py and
py-dev, it is both possible and simpler to write __init__
itself as a generator function, thereby returning a
generator-iterator object with the requisite __init_() and
next() methods.. Since this does not seem to be obvious to
many people, I would agree that *this* should be
mentioned in the docs. All the rest of the discussion about
access and static methods is irrelevant for this purpose.
>>> from __future__ import generators
>>> class Range10:
... def __init__(self,scale):
... self.scale = scale
... def __iter__(self):
... scale = self.scale
... for i in range(10): yield i * scale
...
>>> for i in Range10(4):
... print i
...
0
4
8
12
16
20
24
28
32
36
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=696777&group_id=5470