Причиной неожиданного исключения StopIteration
в main
является то, что ваш вызов m.send(None)
приводит к исчерпанию вашего генератора middle2
(после того, как вспомогательный генератор sales_sum
выходит из цикла в ответ наценность фальси это получила).Когда генератор исчерпан, он поднимает StopIteration
.Обычно это невидимо, потому что вы используете итераторы в циклах for
, но в этом случае это нарушает ваш код.
Существует несколько способов исправить это.Можно было бы использовать вызов с двумя аргументами next
вместо использования m.send(None)
:
next(m, None)
Это делает то же самое, что и m.send(None)
, но имеет дополнительное преимущество подавления StopIteration
.Обратите внимание, что None
в вызове next
на самом деле не совпадает с * в 1019 *.Это возвращаемое значение по умолчанию в случае исчерпанного итератора, а не значение, которое отправляется (которое всегда None
при использовании next
).
Другим подходом было бы изменить middle2
такчто это не заканчивается, когда генератор sales_sum
делает.Вы можете добавить дополнительный оператор yield
в конце, чтобы он возвращал управление в последний раз после выполнения присваивания для final_result
, когда его суб-генератор возвращает.
Последняя идея - заменить m.send(None)
с m.close()
.Это потребует некоторых изменений в final_result
, так как вызов close
вызовет исключение GeneratorExit
в генераторе.Если вы ожидаете этого, вы можете использовать его в качестве сигнала для выполнения вместо поиска фальшивого значения:
def sales_sum(pro_name):
total = 0
nums = []
while True:
try:
x = yield
except GeneratorExit:
return total, nums
print(pro_name+" Sales volume: ", x)
total += x
nums.append(x)
С этим изменением middle2
не будет нуждаться в каких-либо изменениях.