HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonModerate

Article start exercise

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
exercisearticlestart

Problem

I've used encountered this exercise from a tutorial:


Create a function that takes a string as a parameter and returns True if the initial word of the string passed is an article (“The”, “A”, “An”) and returns False if it isn't an article.


Be careful, if the string starts with “There”, it does not start with an article.

I have written the following code for it:

def startsWithArticle(str):
    '''Return True if the first word of str is "The", "A" or "An"'''

    if(str.startswith("The") and str.find(' ')==3):
        return True
    elif(str.startswith("An") and str.find(' ')==2):
        return True
    elif(str.startswith("A") and str.find(' ')==1):
        return True

    return False


which works as expected. I tested it using:

print('"A boy" returned', startsWithArticle("A boy"))
print('"An apple" returned', startsWithArticle("An apple"))
print('"The cat" returned', startsWithArticle("The cat"))
print('"Abyss" returned', startsWithArticle("Abyss"))
print('"There" returned', startsWithArticle("There"))
print('"Ant" returned', startsWithArticle("Ant"))


and this gave the expected output:

"A boy" returned True
"An apple" returned True
"The cat" returned True
"Abyss" returned False
"There" returned False
"Ant" returned False


Is there anything to improve in the function? Do note that I'm a beginner in python. BTW, I'm using python 3.4.3

Solution

Style

Python has a style guide called PEP8 which is definitly worth a read.

A few things can be improved :

-
function name does not respect convention

-
missing whitespaces

-
useless parenthesis

-
name str hides builtin str

Then your code becomes :

def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''

    if string.startswith("The ") and string.find(' ') == 3:
        return True
    elif string.startswith("An ") and string.find(' ') == 2:
        return True
    elif string.startswith("A ") and string.find(' ') == 1:
        return True

    return False

print('"A boy" returned', starts_with_article("A boy"))
print('"An apple" returned', starts_with_article("An apple"))
print('"The cat" returned', starts_with_article("The cat"))
print('"Abyss" returned', starts_with_article("Abyss"))
print('"There" returned', starts_with_article("There"))
print('"Ant" returned', starts_with_article("Ant"))


Don't Repeat Yourself

You are doing the same thing multiple times. You could try to see what is similar and what changes and see if you can use a relevant data structures for the changing parts.

Here I stored the articles in a list to be able to iterate over them.

def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    for article in ["The ", "An ", "A "]:
        if string.startswith(article) and string.find(' ') == len(article) - 1:
            return True

    return False


Don't repeat yourself (again)

You are looking for the article followed by a space and then you check if there is a space in the wanted position. There is no need for that check.

def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    for article in ["The ", "An ", "A "]:
        if string.startswith(article):
            return True

    return False


Don't repeat yourself (again again)

I have to repeat the whitespace in the different elements of the list I a using. This is easy to forget if I ever need to add an article. Let's add the space as part of the logic.

def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    for article in ["The", "An", "A"]:
        if string.startswith(article + ' '):
            return True
    return False


More Python good stuff

The any builtin seems to do what you are doing. Let's use it.

def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    return any(string.startswith(article + ' ')
        for article in ["The", "An", "A"])


The best option: reading the documentation

If we look at the startswith documentation, we have:


prefix can also be a tuple of prefixes to look for.

At that point, your problem is pretty much solved :-)

Code Snippets

def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''

    if string.startswith("The ") and string.find(' ') == 3:
        return True
    elif string.startswith("An ") and string.find(' ') == 2:
        return True
    elif string.startswith("A ") and string.find(' ') == 1:
        return True

    return False

print('"A boy" returned', starts_with_article("A boy"))
print('"An apple" returned', starts_with_article("An apple"))
print('"The cat" returned', starts_with_article("The cat"))
print('"Abyss" returned', starts_with_article("Abyss"))
print('"There" returned', starts_with_article("There"))
print('"Ant" returned', starts_with_article("Ant"))
def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    for article in ["The ", "An ", "A "]:
        if string.startswith(article) and string.find(' ') == len(article) - 1:
            return True

    return False
def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    for article in ["The ", "An ", "A "]:
        if string.startswith(article):
            return True

    return False
def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    for article in ["The", "An", "A"]:
        if string.startswith(article + ' '):
            return True
    return False
def starts_with_article(string):
    '''Return True if the first word of string is "The", "A" or "An"'''
    return any(string.startswith(article + ' ')
        for article in ["The", "An", "A"])

Context

StackExchange Code Review Q#91904, answer score: 12

Revisions (0)

No revisions yet.