#python #python-3.x #iterator #generator #typeerror
#python #python-3.x #итератор #генератор #ошибка типа
Вопрос:
Я пытаюсь понять функции генератора, и из того, что я прочитал, этот .throw()
метод используется при работе с генераторами, если вы хотите передать внешне сгенерированное значение в середину функции, а не в начале в качестве аргумента.
Я создал функцию генератора для возврата наименьшего 1-значного палиндрома, наименьшего 2-значного палиндрома и так далее, пока количество цифр не будет равно 10.
def isPalindrome(num):
if num == int(str(num)[::-1]):
return True
return False
def palindrome_special():
num = 0
while True:
if isPalindrome(num):
num = (yield num) - 1
num = num 1
for number in palindrome_special():
print(number)
num_digits = len(str(number))
if num_digits <= 10:
palindrome_special().send(10 ** num_digits)
Этот код возвращает ошибку типа, хотя:
Трассировка (последний последний вызов):
Файл «C:/Users/anura/PycharmProjects/Advanced Python/advanced_generators.py «, строка 17, в
palindrome_special().send(10 ** num_digits)
Ошибка типа: не удается отправить значение, отличное от None, только что запущенному генератору
Комментарии:
1. Похоже, с вашей логикой возникла какая-то проблема.
yield num
num = (yield num) - 1
вернется .None
Даже если вы это исправите, значениеnum
всегда будет равно 02. @npk можете ли вы объяснить, почему None не будет возвращен.
3. потому
yeild num
что это утверждение4. @npk почему оператор yield num возвращает None? Не должен ли он возвращать значение .send() 10 ** 1?
5. Я не мог понять логику. Но вместо
num = (yield num) - 1
этого вы можете использоватьyield num; num = num-1
. Пожалуйста, убедитесь, что ваш генератор работает должным образом, без окончательного раздела цикла for
Ответ №1:
Вы должны отметить, что вы можете передавать генератору / сопрограмме значение «not None» только в том случае, если его состояние «приостановлено». Генераторы имеют 4 состояния: СОЗДАНО — ПРИОСТАНОВЛЕНО — ЗАКРЫТО — ЗАПУЩЕНО
def coroutine():
var = yield
print(var)
obj = coroutine()
try:
obj.send(4)
except StopIteration:
pass
В этом случае вы снова получите эту ошибку, потому что это состояние СОЗДАНО.
теперь давайте попробуем:
def coroutine():
print('changing state to SUSPEND')
var = yield
print(var)
obj = coroutine()
next(obj)
try:
obj.send(4)
except StopIteration:
pass
Как вы можете видеть, я сначала изменяю его состояние на SUSPEND с помощью next(), чтобы теперь он был готов принять значение. Точка выполнения генератора теперь находится прямо перед оператором ‘yield’.
Позвольте мне добавить, что next() делает то же самое, что и send(None) . Итак, вы могли бы использовать obj.send(None)
в первом примере, который я написал.