what are the advantage of using iter over list

numbers = [7 , 4 , 11 , 3]
iter ( numbers )

I saw suggested as being the preferred way to iterate over a set of objects. I have generally used list.

The idea is that you can assign a name to the instance of your list iterator, which becomes a ‘list_iterator object’. Now you can use said object to call the next number in the list, at any point in the script, rather than at a set point, which is what a loop would do.

numbers = [7, 4, 11, 3]
number = iter(numbers)

# some code
# some more code
print(next(number))
# some more code
# some more code
print(next(number))
...

You could also code that as number = iter([7, 4, 11, 3])

Perhaps a more convincing use case would be if you had a list of week day names; you could then simply have print(next(day)), for example.

To add…
Remember: you can’t iterate over an object more than once (unless you re-initialize it); they are single-use only and as such you should design your code to catch such usage. How you do that would depend on the use case. You could simply catch the Exception, or you could use the sentinel option to call a routine to return something when the iteration is at an end.

Iterators are not generally “preferred” over other methods of iteration. A simple for-each loop is by far the most common way to iterate over sequences. But iterators are useful in certain situations.

One use-case for iterators is distributing objects into variable-sized containers:

things = [1, 2, 3, 4, 5]
boxes = iter([Box(size=2), Box(size=1), Box(size=3)])
box = next(boxes)

for thing in things:
    box.put(thing)
    if box.is_full:
        box = next(boxes)
1 Like

If you have a list numbers and you want to iterate over it, you should
not do this:

for number in iter(numbers):
    pass

That’s a waste of time. numbers is already iterable, you don’t need to call iter() on it. It is rare to need to call iter() on a list or other sequence.

The reason iterators are often preferred is to avoid creating a list in the first place. To create a list, you have to generate all the values up front, before you can use any of them. That might be time consuming or expensive. But with an iterator, you can generate the items one at a time, only as needed.

For example, let’s read a file. Files can be small, or they can be enormous. The old way to read a file is:

with open("myfile.txt") as f:
    for line in f.readlines():
        process(line)

That reads the entire file into memory, all at once. If the file is small, that’s no big deal. If the file is 5 GB, that is a problem. Especially if you stop after the second line and ignore the rest.

So the better way is to use the file object f:

with open("myfile.txt") as f:
    for line in f:
        process(line)

Notice that you still don’t have to call iter() yourself.

Ha ha, I answered your question without actually answering your question, sorry :slight_smile:

Iterators have the advantage that they can generate values one at a time, as needed, instead of having to produce them all up front. That can, sometimes, use less memory and get started quicker.

But if you already have all your values in a list, there is no advantage to converting it into an iterator. Just use the list.

Just an example of how you can use iter() with a for loop. This is a case where you want to advance the iteration inside the loop’s body:

text_iter = iter('Hi *Jack* and *John*!')

for character in text_iter:
    if character == '*':
        while (character := next(text_iter, '*')) != '*':
            print(character, end='')
        print()

The code extracts text between pair of * characters.

The for loop creates an iterator automatically for you but this iterator is not accessible. If you want to work with the iterator you have to create it explicitly and assign it to a variable.

1 Like

Got it - thanks to all