Ошибка типа, сгенерированная при использовании метода отправки для только что созданного объекта генератора

#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 всегда будет равно 0

2. @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) в первом примере, который я написал.