user1179317
user1179317

Reputation: 2903

Iterables/generators explanation

Can somebody explain how the __next__ works with the code below? I know 'next' is used for iterators to grab the next item of an iterable, usualy with next().

I know the __iter__ part gets executed because of list() call which executes __next__. But __next__keeps executing, almost like a while loop? Until StopIteration is executed?

Also, where are all the 'return' elements getting stored under __next__? Is it all just stored in memory until return self under __iter__ returns it to the calling function?

class FRange(object):
    def __init__(self, start, stop=None, step=None):   
        if stop is None:
            self.i = 0
            self.stop = start
            self.step = 1
        elif step is None:
            self.i = start
            self.stop = stop
            self.step = 1
        else:
            self.i = start
            self.stop = stop
            self.step = step

    def __iter__(self):
        return self

    def __next__(self):                             
        if self.i < self.stop and self.step > 0:
            self.i += self.step
            return self.i - self.step
        elif self.i > self.stop and self.step < 0:
            self.i += self.step
            return self.i - self.step
        else:
            raise StopIteration


def rangeFloat(args):
    return list(FRange(*args))  

The code above produces for example:

For args = [-1.1, 2.4, 0.3], the output is
rangeFloat(args) = [-1.1, -0.8, -0.5, -0.2, 0.1, 0.4, 0.7, 1, 1.3, 1.6, 1.9, 2.2].

Upvotes: 0

Views: 35

Answers (1)

user2357112
user2357112

Reputation: 280485

list basically works like

def list(thing):
    result = []
    for item in thing:
        result.append(item)
    return result

and a for loop:

for item in thing:
    # loop body

works like

iterator = iter(thing):
while True:
    try:
        item = next(iterator)
    except StopIteration:
        break
    # loop body

Putting these things together, list calls your FRange instance's __iter__ method to get an iterator; in this case, the iterator is your FRange instance itself. It then calls __next__ repeatedly and appends all __next__ return values to the list until __next__ raises StopIteration. Once StopIteration is raised, list returns the list it built.

Upvotes: 2

Related Questions