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