0

Lets say I have the following code

def top():
    counter = 0

    for ch in child_1():
        print(ch)
        counter += 1

        if counter > 2:
            break


def child_1():
    for ch in child_2():
        yield ch

    print("child_1 logic has finished")


def child_2():
    for ch in "123456789":
        yield ch

    print("child_2 logic has finished")


if __name__ == '__main__':
    top()

Is there a way to have top() method to exit in the middle of the iteration like I have the counter condition, but let the children to finish their logic? (get to the code after the yield statement)

I tried to use while loop and other python tricks but it all went unsuccessful, I don't think there's a way without modifying the nested generators to not be a generators but I'm trying my shot here :D

Paz
  • 72
  • 6
  • Does this answer your question? [Stop generator from within block in Python](https://stackoverflow.com/questions/3164785/stop-generator-from-within-block-in-python) – ti7 Nov 17 '22 at 15:28
  • 1
    I want it due to internal architecture issue we have, to make a workaround without a total refactor for the time being. This is the issue when simplifying it :D – Paz Nov 17 '22 at 15:31
  • If you need `top` to stop, but the children to keep going, maybe your logic is backwards and the children are really the `top`. However, going by your current example you are just bunny-hopping the child2 generator, meaning the `top` and `middle` are completely unnecessary. – OneMadGypsy Nov 17 '22 at 15:38

2 Answers2

3

If you want the children to "finish" what they're doing (i.e. perform the rest of the iteration), keep a reference to the iterator, and exhaust it after you break:

def top():
    counter = 0

    iter_1 = child_1()
    for ch in iter_1:
        print(ch)
        counter += 1

        if counter > 2:
            break

    for _ in iter_1:
        pass
Samwise
  • 68,105
  • 3
  • 30
  • 44
  • There is also [this question](https://stackoverflow.com/questions/36763084/how-to-efficiently-exhaust-an-iterator-in-a-oneliner) about ways to exhaust an iterator. – Thierry Lathuille Nov 17 '22 at 15:46
1

You don't have to stop the top loop. You just need to stop doing the logic in the top loop. You can do this by moving your condition to the top, and using continue instead of break.

def top():
    counter = 0

    for ch in child_1():
        if counter > 2: #continue here instead of break after
            continue

        counter += 1

def child_1():
    for ch in child_2():
        yield ch

    print("child_1 logic has finished")


def child_2():
    for ch in "123456789":
        yield ch

    print("child_2 logic has finished")
OneMadGypsy
  • 4,640
  • 3
  • 10
  • 26
  • Only when the loop body ends with the condition. – ILS Nov 17 '22 at 15:58
  • 1
    @ILS - I wrote this based on their example. Give me more specific examples and I'll write more specific answers. I've been programming since hard-drives were made out of cassette tapes and I can't think of a single time that I needed to stop a parent loop and keep the children running. This is all patchwork. – OneMadGypsy Nov 17 '22 at 16:00