Testing for empty iterators?

Discussion in 'Python' started by Roy Smith, Jul 3, 2004.

  1. Roy Smith

    Roy Smith Guest

    In the old days, if I wanted to return a sequence of items, I'd return a
    list, and loop over it like this:

    for thing in getListOfThings ():
    do something

    With iterators, I'm doing:

    for thing in getThingIterator ():
    do something.

    Now I need to test to see if the iterator is empty. Actually, it's a
    unit test where I want to assert that it is empty. In the old days, I
    would have done:

    assertEquals (getListOfThings (), [])

    but I don't see any clean way to do this with an iterator. The best I
    can come up with is something like:

    flag = False
    for thing in getThingIterator ():
    flag = True
    break
    assertEquals (flag, False)

    Is that really the only way to do it?
    Roy Smith, Jul 3, 2004
    #1
    1. Advertising

  2. Roy Smith

    Roy Smith Guest

    I wrote:

    > flag = False
    > for thing in getThingIterator ():
    > flag = True
    > break
    > assertEquals (flag, False)
    >
    > Is that really the only way to do it?


    Oh, never mind, I got it...

    assertEquals (list (getThingIterator ()), [])
    Roy Smith, Jul 3, 2004
    #2
    1. Advertising

  3. Roy Smith

    Paul McGuire Guest

    "Roy Smith" <> wrote in message
    news:...
    > I wrote:
    >
    > > flag = False
    > > for thing in getThingIterator ():
    > > flag = True
    > > break
    > > assertEquals (flag, False)
    > >
    > > Is that really the only way to do it?

    >
    > Oh, never mind, I got it...
    >
    > assertEquals (list (getThingIterator ()), [])


    In general, I'd say your first approach was better, or something like:

    try:
    getThingIterator.next()
    assert False, "getThingIterator pointed to non-empty iterable"
    except StopIteration:
    pass # no need to assert, by getting here, we know that getThingIterator
    pointed to an empty iterable

    Or if you'd prefer a more typical-looking assert:

    expectedNullItem = null
    try:
    expectedNullItem = getThingIterator.next()
    except StopIteration:
    pass
    assert expectedNullItem==null, "getThingIterator was supposed to be empty"


    Suppose your iterator, through some bug in your code, pointed to a list of
    100,000 database records, instead of an empty list as you expected. Making
    a list from this iterator could be very time-consuming, when all you really
    needed to know was that the iterator pointed to at least one element.

    -- Paul
    Paul McGuire, Jul 4, 2004
    #3
  4. Roy Smith

    Roy Smith Guest

    "Paul McGuire" <_rr.com> wrote:
    > Suppose your iterator, through some bug in your code, pointed to a list of
    > 100,000 database records, instead of an empty list as you expected. Making
    > a list from this iterator could be very time-consuming, when all you really
    > needed to know was that the iterator pointed to at least one element.


    I see your point, but this is a unit test. Even more so than normally,
    in a unit test I think clarity of code is more important that
    efficiency. And in this case, it's only inefficient if it fails the
    test, which should never happen :)
    Roy Smith, Jul 4, 2004
    #4
  5. Roy Smith <> wrote in message news:<>...
    > In the old days, if I wanted to return a sequence of items, I'd return a
    > list, and loop over it like this:
    >
    > for thing in getListOfThings ():
    > do something
    >
    > With iterators, I'm doing:
    >
    > for thing in getThingIterator ():
    > do something.
    >
    > Now I need to test to see if the iterator is empty. Actually, it's a
    > unit test where I want to assert that it is empty. In the old days, I
    > would have done:
    >
    > assertEquals (getListOfThings (), [])
    >
    > but I don't see any clean way to do this with an iterator. The best I
    > can come up with is something like:
    >
    > flag = False
    > for thing in getThingIterator ():
    > flag = True
    > break
    > assertEquals (flag, False)
    >
    > Is that really the only way to do it?


    You may want to check this thread:

    http://groups.google.it/groups?q=&rnum=1

    Michele Simionato
    Michele Simionato, Jul 4, 2004
    #5
  6. Roy Smith

    Peter Otten Guest

    Roy Smith wrote:

    > Now I need to test to see if the iterator is empty. Actually, it's a
    > unit test where I want to assert that it is empty. In the old days, I
    > would have done:
    >
    > assertEquals (getListOfThings (), [])
    >
    > but I don't see any clean way to do this with an iterator. The best I


    [and in a follow-up]

    > Oh, never mind, I got it...
    >
    > assertEquals (list (getThingIterator ()), [])


    An alternative would be

    self.assertRaises(StopIteration, getThingIterator().next)

    which is a bit stricter as it will choke if getThingIterator() returns a
    list instead of an iterator.

    Peter
    Peter Otten, Jul 4, 2004
    #6
  7. Roy Smith

    Paul Rubin Guest

    Peter Otten <> writes:
    > An alternative would be
    >
    > self.assertRaises(StopIteration, getThingIterator().next)


    Note that all those methods "consume" at least one element of the
    iterator. You need something like ungetc for iterators (untested code):

    class wrapper:
    def __init__(self, iterator):
    self.iterator = iterator
    self.pushback = []
    def __next__(self):
    if self.pushback:
    return self.pushback.pop(0)
    def is_empty(self):
    if self.pushback:
    return False
    try:
    self.pushback.append(self.iterator.next())
    return False
    except StopIteration:
    return True

    Maybe something like that should go into itertools, if it's not
    already there. Or the is_empty operation could be built into iterators.
    Paul Rubin, Jul 4, 2004
    #7
  8. Roy Smith

    Larry Bates Guest

    Normally I add a __len__ method to my class
    that contains an iterator if I need to keep
    track of length/empty status. Basically it
    is something like:

    class getListOfThing:
    def __init__(self):
    self.ListOfThings=[]
    self.next_index=0
    #
    # Code to build ListOfThings can be inserted here
    # or in some other method.
    #
    return

    def __iter__(self):
    return self

    def next(self):
    #
    # Try to get the next Thing
    #
    try: Thing=self.ListOfThings[self.next_index]
    except IndexError:
    self.next_index=0
    raise StopIteration
    #
    # Increment the index pointer for the next call
    #
    self.next_index+=1
    return Thing

    def __len__(self):
    return len(self.ListOfThings)
    #
    # Where ListOfThings is an attribute
    # (list) that is defined in __init__
    # and appended to in some way.
    #

    if __name__=="__main__":

    T=getListOfThings()
    print "Length of ListOfThings=",len(T)
    for Thing in T:
    # do something with Thing

    But most of the time the fact that the iterator
    doesn't return enything, so the loop is skipped
    automatically is sufficient. I think you can do
    this same thing with a yield, but this method works
    and I continue to use it a lot.

    HTH,
    Larry Bates
    Syscon, Inc.

    "Roy Smith" <> wrote in message
    news:...
    > In the old days, if I wanted to return a sequence of items, I'd return a
    > list, and loop over it like this:
    >
    > for thing in getListOfThings ():
    > do something
    >
    > With iterators, I'm doing:
    >
    > for thing in getThingIterator ():
    > do something.
    >
    > Now I need to test to see if the iterator is empty. Actually, it's a
    > unit test where I want to assert that it is empty. In the old days, I
    > would have done:
    >
    > assertEquals (getListOfThings (), [])
    >
    > but I don't see any clean way to do this with an iterator. The best I
    > can come up with is something like:
    >
    > flag = False
    > for thing in getThingIterator ():
    > flag = True
    > break
    > assertEquals (flag, False)
    >
    > Is that really the only way to do it?
    Larry Bates, Jul 6, 2004
    #8
    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. John

    empty/non-empty element

    John, Jul 15, 2003, in forum: XML
    Replies:
    1
    Views:
    1,009
    Klaus Johannes Rusch
    Jul 16, 2003
  2. Marcin Kaliciñski

    Iterators and reverse iterators

    Marcin Kaliciñski, May 8, 2005, in forum: C++
    Replies:
    1
    Views:
    475
    Kai-Uwe Bux
    May 8, 2005
  3. Bengt Richter

    Re: recognizing empty iterators

    Bengt Richter, Jul 22, 2003, in forum: Python
    Replies:
    1
    Views:
    296
    John Roth
    Jul 22, 2003
  4. Steven Taschuk

    Re: recognizing empty iterators

    Steven Taschuk, Jul 22, 2003, in forum: Python
    Replies:
    5
    Views:
    290
    Alan Kennedy
    Jul 23, 2003
  5. , India
    Replies:
    10
    Views:
    1,057
    James Kanze
    Aug 8, 2009
Loading...

Share This Page