Вопрос или проблема
У меня есть словарь DICTIONARY, где ключи – это английские буквы, а значения – слова, начинающиеся с соответствующей буквы. Начальное заполнение DICTIONARY выглядит следующим образом:
DICTIONARY = {
'a': 'яблоко',
'b': 'банан',
'c': 'кот',
'd': 'собака',
...
}
Я пытаюсь написать корутину с именем alphabet, которая принимает буквы в качестве входных данных и возвращает слова, ассоциированные с данной буквой из DICTIONARY.
Пример входных данных 1:
coro = alphabet()
next(coro)
print(coro.send('a'))
print(coro.send('b'))
print(coro.send('c'))
Пример выходных данных 1:
text
яблоко
банан
кот
Пример входных данных 2:
python
coro = alphabet()
next(coro)
for letter in 'qwerty':
print(coro.send(letter))
Пример выходных данных 2:
text
перепел
морж
слон
кролик
тигр
як
Мой код использует 2 yield, 1 из которых назначается как переменная:
def alphabet():
while True:
ch = yield
yield DICTIONARY[ch]
Однако 2 оператора yield, используемые в корутине, фактически пропускают 1 значение:
Тестовый ввод:
coro = alphabet()
next(coro)
print(coro.send('a'))
print(coro.send('b'))
print(coro.send('c'))
Правильный вывод:
яблоко
банан
кот
Вывод вашего кода:
яблоко
None #это проблема
кот
Я не знаю, как справиться с None, и он пропускает ‘b’ для банана.
Обновлено:
#все еще не понимаю, как это работает
def alphabet(letter="a"):
while True:
letter = yield DICTIONARY[letter]
Ответ или решение
Для реализации корутины alphabet
, которая будет правильно обрабатывать вводимые буквы и возвращать соответствующие слова из словаря DICTIONARY
, необходимо учитывать, что использование двух операторов yield
может привести к пропуску значений. Это происходит из-за того, что перед первым yield
происходит блокировка, и функция останавливается до следующего вызова send
.
Вот корректное решение с подробным объяснением:
DICTIONARY = {
'a': 'apple',
'b': 'banana',
'c': 'cat',
'd': 'dog',
'q': 'quail',
'w': 'walrus',
'e': 'elephant',
'r': 'rabbit',
't': 'tiger',
'y': 'yak',
}
def alphabet():
while True:
ch = yield # Получаем букву через send, ничего не возвращаем сразу
yield DICTIONARY.get(ch, "Слово не найдено") # Возвращаем слово или сообщение если буква не найдена
# Пример использования
coro = alphabet() # Создаем корутину
next(coro) # Запускаем корутину до первого yield
# Отправляем буквы и выводим соответствующие слова
print(coro.send('a')) # apple
print(coro.send('b')) # banana
print(coro.send('c')) # cat
# Пример для других букв
for letter in 'qwerty':
print(coro.send(letter)) # quail, walrus, elephant, rabbit, tiger, yak
Объяснение кода:
-
Первый yield:
ch = yield
— эта строка извлекает букву из вызоваsend
. При этом сама корутина "приостанавливается", пока не будет вызван следующийsend
. -
Второй yield:
yield DICTIONARY.get(ch, "Слово не найдено")
— здесь происходит поиск слова в словареDICTIONARY
по переданной букве. Использование методаget
позволяет избежать ошибки KeyError, возвращая сообщение "Слово не найдено", если буква отсутствует в словаре.
Почему ваш код не работал:
В вашем первоначальном решении с двумя yield
вы сначала получали букву, но затем возвращали значение сразу после этого, что означало, что при вызове coro.send(letter)
метод send
фактически вызывает второй yield
, откуда возвращается None
. Это и приводит к пропуску слова, так как program flow "перескакивает" значение из первого yield
.
Заключение
Теперь ваша корутина работает корректно и возвращает требуемые слова для каждой буквы. Используйте предложенное решение, чтобы избежать пропусков и получить корректный вывод.