Python Forum

Full Version: Stacking generators
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
So I have a class where an algorithm in a method of the base class needs to iterate things that will depend on the derived class:

class BaseClass(object):
    def __init__(self,string):
        self.string=string

    def iterateChars(self):
        print ','.join([c for c in self.generator()])
This is easily implemented when the derived class has a simple generator:

class DerivedWithSingleGenerator(BaseClass):
    def __init__(self,string):
        super(DerivedWithSingleGenerator,self).__init__(string)
        
    def generator(self):
        for c in '+'.join([c for c in self.string]):
            yield c
Now, things get complicated because another derived class may require two rather different generators (and I don't really want to define different classes just for this). The best I can come up with is to have the generator expected by the parent class select one of the possible generators and iterate it:

       
class DerivedWithComplexGenerator(BaseClass):
    def __init__(self,string,uc):
        super(DerivedWithComplexGenerator,self).__init__(string)
        self.uc=uc
        
    # one of the possible generators
    def lcGenerator(self):
        for c in self.string.lower():
            yield c
            
    # the other possible generator
    def ucGenerator(self):
        for c in self.string.upper():
            yield c
        
    # So this generator ends up iterating another generator 
    def generator(self):
        gen=self.ucGenerator() if self.uc else self.lcGenerator()
        for c in gen:
            yield c
Some test code:

sg=DerivedWithSingleGenerator('aBcdEFg')
sg.iterateChars()

cgu=DerivedWithComplexGenerator('aBcdEFg',True)
cgu.iterateChars()

cgl=DerivedWithComplexGenerator('aBcdEFg',False)
cgl.iterateChars()
The code above is a bit artificial but demonstrates the problem. IRL I'm iterating strokes in Gimp paths, and in some cases re-splitting the strokes...

So, the question: can you think of a better way? Can there be  some unforeseen problem when a generator iterates another? I also thought about a "factory" method in the derived class to return the generator to use but it makes the simple case more complex just to support the more complex case.
Why not just return the appropriate generator:

def generator(self):
    if self.uc:
        return self.ucGenerator()
    else:
        return self.lcGenerator()
Then you're not generating over a generator, you're just providing the correct generator to the original iteration.
(Sep-18-2016, 08:21 PM)ichabod801 Wrote: [ -> ]Why not just return the appropriate generator:

def generator(self):
    if self.uc:
        return self.ucGenerator()
    else:
        return self.lcGenerator()
Then you're not generating over a generator, you're just providing the correct generator to the original iteration.

** Slaps forehead ** Doh... In my "factory" method I was returning self.ucGenerator and not self.ucGenerator(). These parens make a huge difference...

ichabod801.virtual_beers+=1