re.finditer has some length but I'm unable to iterate over it

Question:

Following code block works and it seems pretty legit to me. There is TP two times in TP Tutorials Point TP string so the number of matches should be 2. Also the iteration over this list should work.

s = 'TP Tutorials Point TP'

out = re.findall(r'TP', s)

assert len(list(out)) == 2

# this loop will print 2 times matched string
for m in out:
    print(m)

But what is going on here?

s = 'TP Tutorials Point TP'

out = re.finditer(r'TP', s)

# seems OK so far
assert len(list(out)) == 2

# !!! no output here !!!
for m in out:
    print(m)

Why I’m unable to iterate over returned output of finditer method? In following post it is shown that finditer should also work. My python version: 3.8.10

Asked By: Wakan Tanka

||

Answers:

re.finditer, as the name implies, returns an iterator. When you use len(list(out)) you consume the iterator, and from then on it is empty.

You can test it like so:

assert len(list(out)) == 2 # First will work
assert len(list(out)) == 2 # Second won't

Just remove the assert line and you’ll receive output:

out = re.finditer(r'TP', s)

# We love output :D
for m in out:
    print(m)

For more info, you can consult this question.

Answered By: Bharel

Your issue is with this line:

assert len(list(out)) == 2

Once you execute list(out) you exhaust the iterator and then when you try to iterate it again there is nothing left. If you remove that line from your code it works fine:

s = 'TP Tutorials Point TP'

out = re.finditer(r'TP', s)

# lots of output!
for m in out:
    print(m)

Output:

<re.Match object; span=(0, 2), match='TP'>
<re.Match object; span=(19, 21), match='TP'>
Answered By: Nick
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.