Возвращаемое значение метода генератора throw

#python #generator #return-value #yield #throw

#python #генератор #возвращаемое значение #выход #throw

Вопрос:

В справке throw говорится:

метод throw(…) встроенного экземпляра генератора throw(typ[,val[,tb]]) -> вызвать исключение в генераторе, вернуть следующее полученное значение или вызвать остановку

«вернуть следующее полученное значение» это моя проблема!

Давайте посмотрим на этот пример:

 def gen():
    counter = 1
    while True:
        try:
            yield counter
            counter  = 1
        except Exception as e:
            print("Exception and tpye: ", e, type(e))
            

x = gen()
print("Result of first next call: ", next(x))
res = x.throw(ValueError("Whatever!"))
print("result of throw call: ", res)
print("Result of first next call: ", next(x))
  

Вывод выглядит следующим образом:

 Result of first next call:  1
Exception and tpye:  Whatever! <class 'ValueError'>
result of throw call:  1
Result of first next call:  2
  

Разве возвращаемое значение throw не должно быть 2 вместо одного? В файле справки указано «вернуть СЛЕДУЮЩЕЕ полученное значение2», а не «вернуть повторно ранее полученное значение»

Я боюсь, что я получил что-то совершенно неправильное?

Ответ №1:

При использовании gen.throw(...) в yield инструкции возникает исключение.

Пока вы его перехватываете, следующее увеличение счетчика не выполняется. Вы можете переместить его в finally: -предложение, чтобы гарантировать, что, несмотря ни на что, вы всегда увеличиваете counter :

 def gen():
    counter = 1
    while True:
        try:
            yield counter
        except Exception as e:
            print("Exception and type: ", e, type(e))
        finally:
            counter  = 1
  

Комментарии:

1. Большое вам спасибо. Моя проблема не в том, чтобы запустить этот пример, а в том, чтобы понять — на мой взгляд — странное поведение возврата. Он не выполняет то, что указано в файле справки. Очевидно, throw возвращает самое последнее значение?

2. Нет, он возвращает следующее полученное значение. Но поскольку вы не увеличиваете counter свой код при возникновении исключения, он снова выдаст тот же alue .

3. Хорошо, спасибо. Я понял. Теперь это имеет смысл.

Ответ №2:

Поместите счетчик перед yield:

 counter  = 1
yield counter
  

В противном случае первый результат будет с counter==1 .