Python Forum
Stacking generators - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Stacking generators (/thread-80.html)



Stacking generators - Ofnuts - Sep-18-2016

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.


RE: Stacking generators - ichabod801 - Sep-18-2016

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.


RE: Stacking generators - Ofnuts - Sep-18-2016

(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