Please correct my loop to check if a string contains vowels (Python)?

Viewed 2187

I typed the following to check if a string contains vowels, but seems to have something wrong as it reports first letter to be non-vowel for the whole word.

What should I do?

def vowel(s):
    s = str(s)
    s = s.lower()
    vowel = ("a", "e", "i", "o", "u")
    for char in s:
        if char in vowel:
            print("Yes,", s, "contains a vowel.")
            break
        else:
            print("No,", s, "has no vowels contained.")
            break

vowel("apple")
vowel("shh")
3 Answers

The loop breaks on the first character no matter what. You can say that the word has a vowel if the first character is a vowel, but you can't say it doesn't until you've reached the end. Python has a neat construct that's made exactly for this purpose: the for-loop else clause. This only gets triggered if you reach the end of a loop without breaking out.

So you can fix your code by deleting 8 spaces and a break.

def vowel(s):
    s = str(s)
    s = s.lower()
    vowel = ("a", "e", "i", "o", "u")
    for char in s:
        if char in vowel:
            print("Yes,", s, "contains a vowel.")
            break
    else:
        print("No,", s, "has no vowels contained.")

vowel("apple")
vowel("shh")

To optimise this, consider using the built-in function any in addition to the operator in. You can write vowel as a single string and check for containment in that directly:

if any(char in 'aeiou' for char in s):
    print("Yes,", s, "contains a vowel.")
else:
    print("No,", s, "contains no vowels.")

You could even rewrite the condition as

any(map('aeiou'.__contains__ s))

For containment checks, it's often more efficient to use a set to achieve O(1) lookup, but the sequence of vowels is so small I doubt it'll be much slower to just use the default linear search of str.__contains__.

For some very rare cases, like strings of fewer than 5 chars or so, you could reverse the check:

any(map(s.__contains__, 'aeiou'))
def vowel(s):
    s = str(s)
    s = s.lower()
    vowels = ("a", "e", "i", "o", "u")

    for vowel in vowels:
        if vowel in s:
            print("Yes,", s, "contains a vowel.")
            return True

    print("No,", s, "does not contain a vowel.")
    return False

This would be one way of doing it. As soon as a vowel has been found the function returns True thus stops the search. If no vowel is found, the loop terminates and the 'No' statement is printed.

Instead of using an if-else within the for-loop you can rather just have an if to check if a vowel was found. If a vowel was found then print “found” and return from the function. If a vowel was not found that means the for-loop has ended and you can then just print “not found”:

def vowel(s):
    s = str(s)
    s = s.lower()
    vowel = ["a", "e", "i", "o", "u"]

    for char in s:
        if char in vowel:
            print("Yes,", s, "contains a vowel.")
            return
    print("No,", s, "has no vowels contained.")

If you want to count how many of each vowels were found you can use a dictionary:

    vowel = {"a":0, "e":0, "i":0, "o":0, "u":0}
Related