text: Yield From
  Chain iterable using
  yield from
  No argument that generators are crazy useful.
  However, writing generator functions can get messy beyond yielding one sequence.
  Consider this function:
  def range_then_exp(N): for i in range(N): yield i for i in (x**2 for x in range(N)): yield i
  For a given
  N, this yields the numbers 0 to N, then their squares.
  list(range_then_exp(5))
  [0, 1, 2, 3, 4, 0, 1, 4, 9, 16]
  However, a much cleaner way to write that is using
  yield from.
  def range_then_exp(N): yield from range(N) yield from (x**2 for x in range(N))
  list(range_then_exp(5))
  [0, 1, 2, 3, 4, 0, 1, 4, 9, 16]
  More practical Example
  Say you’re playing some table-top game and find yourself doing a lot of dice rolling.
  We could use this to make generic functions.
  import numpy as np def roll_die(numFaces): return np.random.randint(1, numFaces+1) def multiple_dice(numDice, diceFaces): '''Takes a sequence of [numDice]d20 rolls''' yield from (roll_die(diceFaces) for _ in range(numDice))
  def attack_rolls(numEnemies): return [val for val in multiple_dice(numEnemies, diceFaces=20)] def damage_rolls(numEnemies): '''Assuming a greataxe and +2 str!''' return [val+2 for val in multiple_dice(numEnemies, diceFaces=12)]
  attack_rolls(5)
  [13, 5, 9, 17, 4]
  damage_rolls(5)
  [10, 4, 4, 6, 6]
  Neat!
  And if you’re feeling especally lazy…
  def roll_for_me(numEnemies): return [(atk, dmg) for (atk, dmg) in zip(attack_rolls(numEnemies), damage_rolls(numEnemies))]
  roll_for_me(5)
  [(3, 10), (13, 4), (2, 9), (7, 4), (9, 10)]