Why does for loop exit for "" (empty string) in python?
To explain my query I have a simple code snippet below followed by my question.
def count_vowels(s):
num_vowels = 0
for char in s:
if char in 'aeiouAEIOU':
num_vowels = num_vowels + 1
return num_vowels
print(count_vowels(""))
print("" in "aeiouAEIOU")
gives an output
0
True
My doubt:
Why does an empty string ""
returns True
for the expression
"" in "aeiouAEIOU"
But it skips when it is present along with a for loop?
for char in s:
My understanding is that empty strings are a subset of all strings then why it is ignored when the same expression is in the for loop? Feel free to correct me if there is something I am missing here.
Solution 1:
Your understanding is correct: "empty strings are a subset of all strings"
But now let's see what happens when we use for
for a sequence type such as string. Let's say we have:
lst = [1, 2, 3, 4, 5]
for i in lst:
print(i ** 2)
You can just think that it turns into:
index = 0
while True:
try:
i = lst.__getitem__(index)
except IndexError:
break
print(i ** 2)
index += 1
In your Example, when it tries to get even the first item, it will raise an Exception and break out of the loop. So it doesn't even go inside For
loop.
I said "just think" because in for-loop, iter()
is get called on the object (here lst
) and this built-in function will get an iterator out of the object. In order this to be happened the object should implement either the iterable protocol which is either __iter__
or it must support the sequence protocol (the __getitem__()
)).
lst = [1, 2, 3, 4, 5]
it = iter(lst)
try:
while i := next(it):
print(i ** 2)
except StopIteration:
pass
Both str
and list
object have __iter__
so that is the method gets called rather than __getitem__
. (__iter__
has precedence over __getitem__
)
Solution 2:
In the second print command you're asking does ""
appear in "aeiouAEIOU"
and that is True
.
However, the length of ""
is 0. So the for loop doesn't execute even once since there are no items to iterate over.