views:

117

answers:

2

Hi all,

I have a class where each instance is basically of a bunch of nested lists, each of which holds a number of integers or another list containing integers, or a list of lists, etc., like so:

class Foo(list):
    def __init__(self):
        self.extend(
            list(1), list(2), list(3), range(5), [range(3), range(2)]
            )

I want to define a method to walk the nested lists and give me one integer at a time, not unlike os.walk. I tried this:

def _walk(self):
    def kids(node):
        for x in node:
            try:
                for y in kids(x):
                    yield y
            except TypeError:
                yield x
    return kids(x)

But it immediately raises a stopiteration error. If I add a print statement to print each "node" in the first for loop, the function appears to iterate over the whole container in the way I want, but without yielding each node. It just prints them all the first time I call next on the generator.

I'm stumped. Please help!

+1  A: 

It works if you change return kids(x) to return kids(self)

Wai Yip Tung
You're awesome; I'm dumb. Thanks!
twneale
+1  A: 

Here's a function that is a simpler version of your _walk method that does what you want on an arbitrary iterable. The internal kids function is not required.

def walk(xs):
    for x in xs:
        try:
            for y in walk(x):
                yield y
        except TypeError:
            yield x

This could be trivially adapted to work as a method on your Foo object.

Will McCutchen
Good call. Thanks.
twneale