I frequently use a generator that returns a certain class. What I'd like to do is subclass the generator class so that I can use methods on it that are appropriate for generators that yield instances of that class. For example, one of the things I'd like to do is have a method that returns a generator that filters the base generator.
I want to do something like this:
class Clothes(object):
    def __init__(self, generator):
        self.generator = generator
    def get_red(self):
        return (c for c in self.generator if c.color=="red")
    def get_hats(self):
        return (c for c in self.generator if c.headgear)
The clothes class I want to treat as a collection of clothes. The reason I'm not subclassing a collection is that I rarely want to use the whole collection of clothes as is, and usually just need to filter it further. However, I often need the various filtered collections of clothes. If possible, I'd like Clothes to be a generator itself, as that's how I intend to use it, but I get an error when trying to subclass types.GeneratorType.
types.GeneratorType 
is defined as:
def _g():
    yield 1
GeneratorType = type(_g())
as you see, it is not a regular class.
Now, what makes a generator special?
Not much.
To make use of the generator protocol, all one has to do is to implement the iterator protocol.
There is a nice shortcut: you get the next() for free, when your __iter__ is a generator.
And that's exactly how collections.Iterable is defined:
class Iterable(metaclass=ABCMeta):
    @abstractmethod
    def __iter__(self):
        while False:
            yield None
    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterable:
            if any("__iter__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented
So, just use that to build your generator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With