0

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."

Community
  • 1
  • 1
user1179317
  • 2,693
  • 3
  • 34
  • 62

1 Answers1

5

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.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • I still dont understand fully. x = yield just yields None? I thought x = yield is executed when the send function is called, passing attempt to x, then yield true or false back? – user1179317 Apr 06 '17 at 20:33
  • 1
    @user1179317: The `x =` part is executed when you call `send`. When you call `next`, the generator advances to the `yield`, yields `None`, and pauses. When you call `send`, the object you sent becomes the value of the `yield` expression and is assigned to `x`, and the return value of `send` comes from the next `yield`. – user2357112 Apr 06 '17 at 20:37
  • Okay, i think i got it. Thanks – user1179317 Apr 06 '17 at 20:43
  • 1
    @user1179317 hope this link works but here is a [visual](https://www.safaribooksonline.com/library/view/fluent-python/9781491946237/images/flup_1601.png.jpg) from [fluent python](https://www.amazon.com/Fluent-Python-Concise-Effective-Programming/dp/1491946008/ref=sr_1_1?ie=UTF8&qid=1491511629&sr=8-1&keywords=fluent+python) – salparadise Apr 06 '17 at 20:47