-1

i have var DICTIONARY, which is a dictionary where the keys are English letters and the values are words that start with the corresponding letter. The initial filling of DICTIONARY looks like this:

DICTIONARY = {
    'a': 'apple',
    'b': 'banana',
    'c': 'cat',
    'd': 'dog',
    ...
}

i'm trying to write coroutine called alphabet, which takes letters as input and returns the words associated with the given letter from the DICTIONARY.

Sample Input 1:

coro = alphabet()
next(coro)
print(coro.send('a'))
print(coro.send('b'))
print(coro.send('c'))

Sample Output 1:
text
apple
banana
cat

Sample Input 2:
python
coro = alphabet()
next(coro)
for letter in 'qwerty':
    print(coro.send(letter))

Sample Output 2:
text
quail
walrus
elephant
rabbit
tiger
yak

my code uses 2 yields , 1 is assigned as variable:

def alphabet():
    while True:
         ch = yield
         yield DICTIONARY[ch]

however 2 yield statements used in coroutine actually skip 1 value always:

Test input:
coro = alphabet()
next(coro)
print(coro.send('a'))
print(coro.send('b'))
print(coro.send('c'))
Correct output:
apple
banana
cat

Your code output:
apple
None #this is the problem
cat

i dont know how to deal with None and it skips 'b' for banana.

updated:

#still dont really get it how it works
def alphabet(letter='a'):
    while True:

        letter = yield DICTIONARY[letter]
  
    
6
  • 2
    Do you realize that a) next(gen) is equivalent to gen.send(None) and b) yield and yield <something> both consume object fed to .send()? Your problem asks you to 1) load the first character (ch = yield) once, and then 2) yield the word, receiving the next character, and repeat. Commented Oct 7, 2024 at 15:42
  • 1
    And, just for the sake of completeness, please stop calling generators coroutines - these are very related, but different concepts. "coroutine" in python has a well-defined meaning in async world. Commented Oct 7, 2024 at 15:54
  • @STerliakov, i have updated my question, but still kinda dont get it. i understand i need only 1 yield statement Commented Oct 7, 2024 at 15:56
  • 1
    Oh, cool, now you're somewhat closer, but there's no promise that "a" will be the first letter. Try to add print statements before and after every yield. (and you need two yield statements, not only one) Commented Oct 7, 2024 at 15:59
  • 3
    Solutions should be posted below with "Your Answer", not in the question. Commented Oct 7, 2024 at 16:11

1 Answer 1

0

You actually have to use a single yield expression. It's right hand side - the value to be yielded - is evaluated and made available to the driving code (calling code) before the value passed by .send makes it into the function. That value is the result of the yield keyword - and represents the dictionary letter that should be yielded back in the next iteration - when it will generate the value for the letter received in the previous interation, and get a new letter:


DICTIONARY = {word[0]: word for word in ["alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "..."]}

def alphabet():
    next_letter = "a"
    while True:
         next_letter = yield DICTIONARY[next_letter]

Perceive that the initial next call, your code has as next(coro), has exactly the purpose of starting the co-routine and running it up the first time if finds yield. In my fixed example above, we set the initial next_letter to a, so it yields alpha: but since the return value of next(coro) isn't used, this first value is just thrown away. Then execution continues outside the coroutine until the first .send is met - the argument to send becomes the value yield DICTIONARY... resolves to inside the co-routine, and is assigned to the next_letter variable - the while block re-starts execution, and yield DICTIONARY[next_letter] will pass DICTIONARY[next_letter] to the caller, as the return value of send, and so on.

In the form you had written it when asking the question:

def alphabet():
    while True:
         ch = yield
         yield DICTIONARY[ch]

the first yield expression in ch = yield would receive the value passed by the first send, and the second yield would generate the return value for that send: the correct word - but then each even .send would be passed to the yield in the yield DICTIONARY[ch] line, which is not stored and thrown away - only the following send parameter is assigned again to ch.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.