1# yield-from a user-defined generator with a throw() method 2 3class Iter: 4 def __iter__(self): 5 return self 6 7 def __next__(self): 8 return 1 9 10 def throw(self, x): 11 print('throw', x) 12 return 456 13 14def gen(): 15 yield from Iter() 16 17# calling close() should not call throw() 18g = gen() 19print(next(g)) 20g.close() 21 22# can throw a non-exception object 23g = gen() 24print(next(g)) 25print(g.throw(123)) 26 27# throwing an exception class just injects that class 28g = gen() 29print(next(g)) 30print(g.throw(ZeroDivisionError)) 31 32# this user-defined generator doesn't have a throw() method 33class Iter2: 34 def __iter__(self): 35 return self 36 37 def __next__(self): 38 return 1 39 40def gen2(): 41 yield from Iter2() 42 43# the thrown ValueError is not intercepted by the user class 44g = gen2() 45print(next(g)) 46try: 47 g.throw(ValueError) 48except: 49 print('ValueError') 50 51# the thrown 123 is not an exception so raises a TypeError 52g = gen2() 53print(next(g)) 54try: 55 g.throw(123) 56except TypeError: 57 print('TypeError') 58