Simplicity
Simplicity

Reputation: 48916

The proper way of using "yield" in this example

I'm trying to demonstrate how yield in Python is used. I want to demonstrate that through an example.

The example will ask the user to enter yes or no, and increase the counter n by 1 every time yes is entered.

The part I want to show how yield works is when the user calls the function again, and getting an updated value of the number of times. For instance, if return was used, and the user runs the script again, it will start from scratch and the number of times would be 1. Rather, I want the user to get 1,2,3,...etc, that is the number of times yes was entered.

The issue here is how to use yield to demonstrate such example. In the code I wrote below, I always get a generator object returned rather than the value of n. How can I get the integer value n returned instead?

def yes_times(answer):
    n = 0
    if answer == 'yes':
        n = n + 1
        yield n


answer = raw_input('"yes" or "no": ')
times = yes_times(answer)
print 'You answered yes ' + str(times) + ' times'

Thanks.

Upvotes: 2

Views: 248

Answers (3)

For your example, you can try:

def yes_times(answer = None):
    count = 0
    while True:
        if answer=="yes":
            count += 1
            answer = yield count
        else:
            answer = yield count


gen = yes_times()
gen.next()
while True:
    answer = raw_input('"yes" or "no": ')
    print 'You answered yes ' + str(gen.send(answer)) + ' times'

Upvotes: 1

Useless
Useless

Reputation: 67713

I'm trying to demonstrate how yield in Python is used.

... example problem ...

The issue here is how to use yield to demonstrate such example.

You're doing this backwards.

Don't demonstrate how yield is used by picking some arbitrary example, which is unrelated to generator behaviour, and try implementing it using yield.

Instead, choose something that yield is good at, and implement that - ideally with a comparable non-yield implementation so you can show the benefits.


Simple example: toy implementation of range

def naive_range(begin, end):
    i = begin
    result = []
    while i < end:
        result.append(i)
        i = i + 1
    return result

def generate_range(begin, end):
    i = begin
    while i < end:
        yield i
        i = i + 1

Now, can you name the drawbacks of the naive implementation? When will it be significantly worse than the generator, and why?

Upvotes: 4

Prune
Prune

Reputation: 77827

The problem is that you're trying to use the generator as if it were a function. I strongly recommend that you go through a tutorial on line until you grasp the difference -- after all, that's how I quit making exactly this mistake. :-)

Your statement

times = yes_times(answer)

instantiates the generator, which is what you get when you print. Instead, you need to either use the next function ...

times = next(yes_times(answer))

... or properly employ a generator that does what you need. The general use of a generator is to recognize it as a stream of data, something like

for times in yes_times(answer):

However, this requires that you update your generator to get the input itself.

Is that enough to get you moving?

Upvotes: 0

Related Questions