Generators don't quite work like coroutines. If a generator function recursively calls itself, the recursive call produces another generator object. Control doesn't reenter the generator code like it would in something like Lua, and a yield
won't suspend a whole stack of generator calls at once. You have to iterate over the returned generator object and yield its elements:
def parse(d,key):
print('in')
if type(d)==type({}):
if key in d:
yield d[key]
for k in d:
for item in parse(d[k],key):
yield item
if type(d)==type([]):
for i in d:
for item in parse(i,key):
yield item
In Python 3.3, the yield from
syntax for delegating to a subgenerator was added, so the code would reduce to the following:
def parse(d,key):
print('in')
if type(d)==type({}):
if key in d:
yield d[key]
for k in d:
yield from parse(d[k],key)
if type(d)==type([]):
for i in d:
yield from parse(i,key)
This has the advantage of automatically handling send
, throw
, and a bunch of edge cases that explicitly looping over the subgenerator doesn't deal with.