oadams
oadams

Reputation: 3087

Static variable simultaion: classes vs generators

I was curious about using static variables in python, and ended up at: Why doesn't Python have static variables?

In the accepted answer, which I found informative, it is said "If you want your function's behavior to change each time it's called, what you need is a generator".

However I was a bit confused, since the example used there can be done with a class as well:

class Foo(object):                                                              
    def __init__(self, bar):                                                    
        self.bar = bar                                                          

    def __call__(self):                                                         
        self.bar = self.bar * 3 % 5                                             
        return self.bar

foo = Foo(bar)                                                                  
print foo()                                                                     
print foo()

This makes more sense to me (but probably only because I haven't used generators properly before).

So my question is whether there is some other advantage to using generators over classes when the function needs to change behavior each time it's called.

Upvotes: 1

Views: 1190

Answers (4)

Jochen Ritzel
Jochen Ritzel

Reputation: 107686

A proper generator class looks like this:

class Foo(object):                                                              
    def __init__(self, bar):                                                    
        self.bar = bar                                                          

    def __iter__(self):
        return self

    def next(self):
        self.bar = self.bar * 3 % 5                                             
        return self.bar

foo = Foo(3)                                                                  
print next(foo)                                                                     
print next(foo)

The equivalent generator function takes half the code:

def Foo(bar):
    while True:
        bar = bar * 3 % 5   
        yield bar                                                          

foo = Foo(3)                                                                  
print next(foo)                                                                     
print next(foo)

Generator functions are just a shortcut for the most common, basic iteration pattern. When you need something more complex a class allows for that.

Upvotes: 2

user395760
user395760

Reputation:

Generators (the simple ones, not getting into coroutines) have a single, very specific purpose: Writing iterators. To this end, you get implicit capture of local variable and a keyword to suspend (as opposed to "terminate" - you can resume) execution and give the caller the next value of the iterator. The advantages are:

  • The logic reads more naturally, as you don't need to chop it into several method invokations - all state is preserved, including the program counter - you can use control flow across yielding . You could replace yield x with results.append(x) and return results at the end and get a function that's equivalent to list(the_original_generator(...)).
  • You don't need to explicitly make values long-lived by putting them into self - less to type and less to read.
  • You don't need a class declaration with two method declarations (a few lines of boilerplate, which is considerable by Python standards).

You can use the "capture of local variable" thing to implement an iterable which behaves as, except that you can have multiple ones and you don't invoke a function but use an iterator (next_val = next(vals) instead of next_val = vals()). Whether it is appropriate depends.

Upvotes: 3

Vsevolod Dyomkin
Vsevolod Dyomkin

Reputation: 9451

For generators there's no other way to access the variable, except by calling a function, while in a class-based variant, you can modify it directly. This can be both advantage and disadvantage depending on your use-case. Also the code is simpler. For a more detailed discussion see: http://wiki.python.org/moin/Generators

Upvotes: 1

Thomas K
Thomas K

Reputation: 40390

There's nothing you can do with a generator that you couldn't do with a class.

The reason to use generators is simply that they're shorter, and in many cases read more naturally than classes. Obviously this depends what you're doing. In the example you give, you just want to repeatedly perform the same operations and spit out the number, so a generator makes perfect sense. For more complex situations, you'd use a class.

Upvotes: 2

Related Questions