Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skipping iterations inside Python iterator __next__ in a manner similar to continue

I would like to make a Python iterator class using __next__ that skips certain elements.

For example, here I have implemented a generator using yield and continue and I would like the iterator class below it to do exactly the same thing.

def generator_style(my_iter):
    for i in my_iter:
        if i < 999990:
            continue
        yield i


print(", ".join(str(s) for s in generator_style(range(1000000))))

# prints 999990, 999991, 999992, 999993, 999994, 999995, 999996, 999997, 999998, 999999


class iterator_style:
    def __init__(self, my_iter):
        self.my_iter = iter(my_iter)

    def __iter__(self):
        return self

    def __next__(self):
        i = next(self.my_iter)
        if i < 999990:
            # what do I do here??? I can't use continue
            return next(self)
        return i

print(", ".join(str(s) for s in iterator_style(range(1000000))))

# I want it to print 999990, 999991, 999992, 999993, 999994, 999995, 999996, 999997, 999998, 999999

Unfortunately, this version crashes due to

RecursionError: maximum recursion depth exceeded while calling a Python object

It works for smaller numbers though.

I cannot replace the return next(self) line with continue because:

    continue
    ^
SyntaxError: 'continue' not properly in loop
like image 347
Daniel Avatar asked Apr 15 '26 09:04

Daniel


1 Answers

You're correct that recursion has a lot of limitations for algorithms like this. Typically you would want to avoid deep recursion to avoid RecursionErrors. In this case you need to recursively call __next__ 999990 times to get your value.

To avoid this you can use a while-loop instead. Just keep calling next until you reach a value that meets your criteria.

def __next__(self):
    while (i := next(self.my_iter)) < 999990:
        pass
    return i

Another way you could write it, if you find the assignment expression confusing:

def __next__(self):
    while True:
        i = next(self.my_iter)
        if i < 999990:
            continue
        return i
like image 176
flakes Avatar answered Apr 17 '26 23:04

flakes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!