Initially (PEP 380), yield from syntax was introduced to be used for delegating to a "subgenerator." Later it was used with now deprecated generator-based coroutines.
I cannot find out what kind of objects yield from can be applied to in general. My first conjecture was that it only requires __iter__ method on the object to return an iterator. Indeed, the following works with Python 3.8:
class C:
    def __init__(self, n):
        self.n = n
    def __iter__(self):
        return iter(range(self.n))
def g(n):
    yield from C(n)
print(tuple(g(3)))
However, it also works with some awaitables, like asyncio.sleep(1), which do not have __iter__ method.
What is the general rule? What determines if an object can be given as an argument to yield from form?
 
    