Home > Mobile >  Sometimes I want a generator
Sometimes I want a generator

Time:07-27

The following code took me by surprise. I was hoping that I could write a function that might or might not act as a generator.

def mayGen(limit=5, asGenerator=False):
    result = []
    for i in range(1, limit   1):
        n = i * i
        if asGenerator:
            yield n
        else:
            result.append(n)
    return result

print(mayGen(5, False))

for x in mayGen(5, True):
    print(x)

But no, the output of this program is

<generator object mayGen at 0x7fa57b6ea7b0>
1
4
9
16
25

Calling mayGen with asGenerator=False is simply useless. It seems that the mere existence of a yield statement, regardless of whether it is executed, radically changes the behavior of the containing function.

So what if mayGen was actually big and complicated and I wish I could ask it to either function as a generator, or write its computed output to a file? Is there a well-traveled path here? How are people handling this sort of thing?

CodePudding user response:

Just write a generator. You can always take its output and do whatever you want with it: put it in a list, write it to a file, etc. Although, if that's what you're going to be using it for a lot, you might want to write a wrapper function to do it for you, for example:

def willGen(limit=5):
    for i in range(1, limit 1):
        n = i * i
        yield n

def willReturnList(*args, **kwargs):
    return list(willGen(*args, **kwargs))

CodePudding user response:

Edit: For a number of reasons mentioned in comments, this is probably not a great idea. In any event, you can write this:

def mayGen(limit=5, asGenerator=False):
    def _generate(limit):
        for i in range(1, limit   1):
            n = i * i
            yield n
    def _return(limit):
        result = []
        for i in range(1, limit   1):
            n = i * i
            result.append(n)
        return result
    if asGenerator:
        return _generate(limit)
    return _return(limit)

Edit: to simiplify even further, you should probably just return list(_generate(limit)) in the final line.

  • Related