user1179317
user1179317

Reputation: 2903

Python generator coroutine

Trying to understand a bit more of the generator/send function in python. I read some in the link: generator send function purpose which helped a lot.

But I am trying to understand the code below. Why is the next(checker) necessary? Doesnt the send function automatically ask for the next item in the generator? I tried just having the next(checker) before the for loop but that doesnt function the same way. I thought the send function sends 'attempt' as x and yields whether x == password. I just dont understand why its necessary to have the next(checker) in the loop.

def checkPassword(attempts, password):
    def check():
        while True:
            x = yield
            yield x == password

    checker = check()
    for i, attempt in enumerate(attempts):
        next(checker)
        if checker.send(attempt):
            return i + 1

    return -1

The function above is base on the problem:

"In order to validate your function, you want to test it locally. Given a list of attempts and the correct password, return the 1-based index of the first correct attempt, or -1 if there were none.

Example

For attempts = ["hello", "world", "I", "like", "coding"] and password = "like", the output should be checkPassword(attempts, password) = 4."

Upvotes: 0

Views: 1284

Answers (1)

user2357112
user2357112

Reputation: 280465

Doesnt the send function automatically ask for the next item in the generator?

Yeah, but the way this generator is written, half the values come from this yield:

x = yield

which just yields None. The calls to next consume the None.


The generator could have been written differently, to eliminate most of the next calls:

def checkPassword(attempts, password):
    def check():
        x = yield
        while True:
            x = yield x == password

    checker = check()
    next(checker)
    for i, attempt in enumerate(attempts):
        if checker.send(attempt):
            return i + 1

    return -1

However, the yield/send communication between a generator and its user cannot start with a send, since a fresh generator is stopped at the beginning of the function body instead of at a yield that could receive a value. Thus, there always has to be a next (or equivalently a send(None)) before you can start sending values the generator will use.

Upvotes: 5

Related Questions