Reputation: 3087
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
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
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:
yield x
with results.append(x)
and return results
at the end and get a function that's equivalent to list(the_original_generator(...))
.self
- less to type and less to read.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
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
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