iter jitters

Discussion in 'Python' started by Steven Brent, May 4, 2004.

  1. Steven Brent

    Steven Brent Guest

    Hi folks,

    In the snippet below, I'm trying to overload the __iter__ list method:

    def __iter__(self):
    print "using custom iter"
    counter = 0
    end = len(self.data) - 1
    while counter <= end:
    print self.data[counter]
    counter += 1

    It pretty much works, except that the output is ugly when the while loop
    falls off the end of the list:

    >>> L3 = [1,2,3,'x','y',z']


    >>> for item in L3: print item,


    using custom iter
    1
    2
    3
    x
    y
    z
    Traceback (most recent call last):
    File "mylist.py", line 38, in ?
    for item in L3:print item,
    TypeError: iter() returned non-iterator of type 'NoneType'

    Oh, yeah, plus it's adding a newline at the end of each item even though
    I've got the comma there. I'm gonna keep plugging away to see if I can
    figure this out, but stuff like this makes me frustrated... Thanks a
    million.
     
    Steven Brent, May 4, 2004
    #1
    1. Advertising

  2. Steven Brent wrote:

    > In the snippet below, I'm trying to overload the __iter__ list method:
    >
    > def __iter__(self):
    > print "using custom iter"
    > counter = 0
    > end = len(self.data) - 1
    > while counter <= end:
    > print self.data[counter]
    > counter += 1
    >
    > It pretty much works, except that the output is ugly when the while loop
    > falls off the end of the list:
    >


    > File "mylist.py", line 38, in ?
    > for item in L3:print item,
    > TypeError: iter() returned non-iterator of type 'NoneType'
    >
    > Oh, yeah, plus it's adding a newline at the end of each item even though
    > I've got the comma there. I'm gonna keep plugging away to see if I can
    > figure this out, but stuff like this makes me frustrated... Thanks a
    > million.


    I think you've got something wrong here - __iter__ is supposed to return an
    object that supports the iteration protocol - mainly a next() method that
    throws an exception when no more elements are available.

    Today, this kind of thingy is usually done using generators:

    class foo:
    def __init__(self):
    self.data = range(10)

    def __iter__(self):
    def _my_iter():
    for e in self.data:
    yield e
    return _my_iter()


    for i in foo():
    print i



    --
    Regards,

    Diez B. Roggisch
     
    Diez B. Roggisch, May 4, 2004
    #2
    1. Advertising

  3. Even easier:

    """
    class foo:
    def __init__(self):
    self.data = range(10)

    def __iter__(self):
    for e in self.data:
    yield e

    for i in foo():
    print i

    __iter__ may itself be a generator (I mostly use it exactly in this way).

    HTH!

    Heiko.
     
    Heiko Wundram, May 4, 2004
    #3
  4. Steven Brent

    Steven Brent Guest

    OK, thanks ... that explains why my other idea of returning a new list
    to iterate over didn't work either. Talk about chasing one's tail...

    Btw, I just realized that a custom __getitem__ method I defined earlier
    in the module(and unhelpfully didnt post), handles the iteration in 2 lines!

    def __getitem__(self, index):
    return self.data[index]

    This is the kind of thing I was after, because I didn't want any
    iteration going on in the __iter__ definition itself. Trying to reinvent
    the wheel for exercise.

    But generators are cool, and I promise to use them lots :)

    This seems to be a recurring pattern for me; I get deep into confusion
    by skipping over the obvious. Thanks for the clarity and knowledge.

    --Steven the newbie

    ===========================
    Diez B. Roggisch wrote:

    > Steven Brent wrote:
    >
    >
    >>In the snippet below, I'm trying to overload the __iter__ list method:
    >>
    >> def __iter__(self):
    >> print "using custom iter"
    >> counter = 0
    >> end = len(self.data) - 1
    >> while counter <= end:
    >> print self.data[counter]
    >> counter += 1
    >>
    >>It pretty much works, except that the output is ugly when the while loop
    >>falls off the end of the list:
    >>

    >
    >
    >> File "mylist.py", line 38, in ?
    >> for item in L3:print item,
    >> TypeError: iter() returned non-iterator of type 'NoneType'
    >>
    >>Oh, yeah, plus it's adding a newline at the end of each item even though
    >>I've got the comma there. I'm gonna keep plugging away to see if I can
    >>figure this out, but stuff like this makes me frustrated... Thanks a
    >>million.

    >
    >
    > I think you've got something wrong here - __iter__ is supposed to return an
    > object that supports the iteration protocol - mainly a next() method that
    > throws an exception when no more elements are available.
    >
    > Today, this kind of thingy is usually done using generators:
    >
    > class foo:
    > def __init__(self):
    > self.data = range(10)
    >
    > def __iter__(self):
    > def _my_iter():
    > for e in self.data:
    > yield e
    > return _my_iter()
    >
    >
    > for i in foo():
    > print i
    >
    >
    >
     
    Steven Brent, May 4, 2004
    #4
  5. Steven Brent wrote:

    > Btw, I just realized that a custom __getitem__ method I defined earlier
    > in the module(and unhelpfully didnt post), handles the iteration in 2
    > lines!
    >
    > def __getitem__(self, index):
    > return self.data[index]
    >
    > This is the kind of thing I was after, because I didn't want any
    > iteration going on in the __iter__ definition itself. Trying to reinvent
    > the wheel for exercise.


    Interesting. Just played around with my example and found that in case of
    absence of an __iter__-method the for - in generates keys from 0 to - well,
    I guess something like max_int, but I won't wait so long... - and then
    tries __getitem__ with that key.



    --
    Regards,

    Diez B. Roggisch
     
    Diez B. Roggisch, May 4, 2004
    #5
  6. Steven Brent

    Peter Otten Guest

    Heiko Wundram wrote:

    > def __iter__(self):
    > for e in self.data:
    > yield e


    Another option:

    >>> class Foo:

    .... def __init__(self):
    .... self.data = range(10)
    .... def __iter__(self):
    .... return iter(self.data)
    ....
    >>> for i in Foo():

    .... print i,
    ....
    0 1 2 3 4 5 6 7 8 9
    >>>


    Peter
     
    Peter Otten, May 5, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. dw

    bugs at iter file() ?

    dw, Jul 15, 2004, in forum: Python
    Replies:
    0
    Views:
    363
  2. dw
    Replies:
    0
    Views:
    264
  3. Terry Reedy

    Re: bugs at iter file() ?

    Terry Reedy, Jul 15, 2004, in forum: Python
    Replies:
    3
    Views:
    279
    Wolfgang Strobl
    Aug 7, 2004
  4. thomas
    Replies:
    23
    Views:
    866
    James Kanze
    Feb 26, 2008
  5. Gennaro Prota
    Replies:
    1
    Views:
    342
    Gennaro Prota
    Aug 21, 2008
Loading...

Share This Page