Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__iter__() implemented as a generator

I have an object subclass which implements a dynamic dispatch __ iter __ using a caching generator (I also have a method for invalidating the iter cache) like so:

def __iter__(self):
    print("iter called")
    if self.__iter_cache is None:
        iter_seen = {}
        iter_cache = []
        for name in self.__slots:
            value = self.__slots[name]
            iter_seen[name] = True
            item = (name, value)
            iter_cache.append(item)
            yield item           
        for d in self.__dc_list:
            for name, value in iter(d):
                if name not in iter_seen:
                    iter_seen[name] = True
                    item = (name, value)
                    iter_cache.append(item)
                    yield item
        self.__iter_cache = iter_cache
    else:
        print("iter cache hit")
        for item in self.__iter_cache:
            yield item

It seems to be working... Are there any gotchas I may not be aware of? Am I doing something ridiculous?

like image 290
Emanuel Landeholm Avatar asked Jul 05 '12 15:07

Emanuel Landeholm


1 Answers

container.__iter__() returns an iterator object. The iterator objects themselves are required to support the two following methods, which together form the iterator protocol:

iterator.__iter__()

Returns the iterator object itself.

iterator.next()

Return the next item from the container.

That's exactly what every generator has, so don't be afraid of any side-effects.

like image 84
Maksym Polshcha Avatar answered Oct 22 '22 13:10

Maksym Polshcha