简体   繁体   中英

Python infinite recursion with generators

I'm trying to wrap my head around python generators and as a result, I'm trying to print infinitely nested objects using yield, but I find that I still get problems with blowing out the stack. Ideally, I'd like to be able to yield and print each item as it comes along but I can't figure out what I'm doing wrong:

class Parent:    
    def __init__(self, name, child=None):
        self._name = name
        self._child = child

    def get_name(self):
        return self._name

    def get_child(self):
        return self._child

    def set_child(self, child):
        self._child = child

    def __iter__(self):
        next_child = self._child.get_child()
        if not next_child:
            raise StopIteration            
        else:
            self._child = next_child
            yield next_child

    def __str__(self):
        return "%s has %s" % (self._name, self._child)

if __name__ == '__main__':
    p1 = Parent("child")
    p2 = Parent("child", p1)
    p1.set_child(p2)

    for t in p1:
        print t

The error in your code, as noted by jonrsharpe, is due to the __str__ function, which tries to return:

child has child has child has child has child has ...

You probably mean:

def __str__(self):
    return "%s has %s" % (self._name, self._child.get_name()) 
    # return 'child has child'

Also, __iter__ should be a generator function. Generator functions need to contain a loop in order to continually produce values. So it should be something like:

def __iter__(self):
    next_child = self._child.get_child()
    while next_child:            
        yield next_child
        next_child = next_child.get_child()
    # When the function ends, it will automatically raise StopIteration

With the modifications, your code prints endless lines of child has child .

See also What does the yield keyword do in Python? for more information about generator functions.

The infinite recursion is happening at __str__ function. It has nothing to do with the __iter__ function.

when you do print t , it executes t._child.__str__ which in turn executes t._child._child.__str__ and so forth.

try changing the __str__ function definition to something simple like return self._name and you won't get a recursion depth exceeded error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM