Home > Software design >  Why is next() function 'in place' for csv.reader objects but not for list iterators?
Why is next() function 'in place' for csv.reader objects but not for list iterators?

Time:08-13

According to python documentation for next() function:

next(iterator[, default]): Retrieve the next item from the iterator by calling its __next__() method. If default is given, it is returned if the iterator is exhausted, otherwise StopIteration is raised.

My question: Why is it 'in place' when used like below:

import csv

with open('data.csv', 'r') as csv_file:
    csv_reader = csv.reader(csv_file)
    next(csv_reader)
    for row in csv_reader:
        print(row)

This skips the first line of the file. I thought it should be like this instead:

csv_reader = next(csv_reader)

CodePudding user response:

next returns the next item of the iterator, not the "rest" of the iterator after it removes this next item. So if you save the result of next(csv_reader) into csv_reader, you will have the first line of the file saved in csv_reader and will have lost the iterator.

An example:

my_iterator = iter([1, 2, 3])
result = next(my_iterator)
print(result)  # prints 1
second_result = next(my_iterator)
print(second_result)  # prints 2

Notice how we always call next() on the same iterator object. We don't need to reassign it, it just keeps giving us the elements one by one, keeping track which one it should return next.

next can be used to skip some of the elements like so:

my_iterator = iter([1, 2, 3])
next(my_iterator)  # returns 1, but we don't want to store it, we just want to move past it
for element in my_iterator:
    print(element)
# will print 2 and 3

Iterators versus lists

Sometimes there is confusion about iterators and lists. A list itself is not an iterator, but an iterable. That means we can use for x in lst to automatically create an iterator over the list. So

my_list = [1, 2, 3]
for e in my_list:
    pass

actually behind the scenes works somewhat like this:

my_list = [1, 2, 3]

# create an iterator from the list for the loop
my_list_iterator = iter(my_list)
for e in my_list_itetator:
    pass
# and get rid of the iterator after the loop
del my_list_iterator
  • Related