Search code examples
python-3.xraise

Raise statements: Why does my block of code return an empty list instead of executing my "raise" statement?


Firstly, I apologise if my question comes across as stupid or if there are any errors in my post - This is my second post, and I am still finding it difficult how to ask appropriate questions on this platform.

Secondly, I have tried to look up the logic behind the "raise" statement using the examples from the Python Docs website (https://docs.python.org/3/tutorial/errors.html) and another post on Stackoverflow (Raise statement) but I still cannot wrap my head around this "raise" statement.

I am trying to answer the following question from the Ebook Introduction to computation and programming using Python: "Implement a function that satisfies the specification." (See function specification below).

def findAnEven(L):
    """
    ASSUMES: L is a list of integers 
    RETURNS: the first even number in L
    Raises ValueError if L does not contain an even number
    """

Below is my attempt to solve this question:
def findAnEven(L):
    """
    ASSUMES: L is a list of integers
    RETURNS: the first even number in L
    Raises ValueError if L does not contain an even number
    """
    try:
        evenNumbers = []
        for i in L:
            if i % 2 == 0:
                evenNumbers.append(i)
                break
        return(evenNumbers)
    except ValueError:
        raise ValueError("ValueError exception thrown")
findAnEven([1,2,3,4]) # RETURNS: [2]
findAnEven([1,1,1,1]) # RETURNS: [] - THIS SHOULD EXECUTE RAISE STATEMENT, NOT RETURN AN EMPTY LIST            

I am trying to understand why my block of code is only returning an empty list, instead of executing my "raise" statement?

If anyone can explain (in layman terms) why my block of code is returning an empty list to the last function call (i.e., findAnEven([1,1,1,1]) instead of executing my "raise" statement, I would be very grateful - Again apologies for the stupid question!


Solution

  • try:
        evenNumbers = []
        for i in L:
            if i % 2 == 0:
                evenNumbers.append(i)
                break
        return(evenNumbers)
    except ValueError:
        raise ValueError("ValueError exception thrown")
    

    The code in the except block will never be executed since no line in the try block can ever raise a ValueError. In case there are no even numbers in L, the if is never True and return(evenNumbers) just returns the empty evenNumbers list.

    If you want to raise an exception instead of returning an empty list, do that explicitly. I also took the liberty to make your code more pythonic and succinct. Once it finds the first even number it will return a list that contains it. If the return statement is never hit, that means no even number was found, so we raise ValueError with a clear message.

    def find_an_even(L):
        """
        ASSUMES: L is a list of integers
        RETURNS: the first even number in L
        Raises ValueError if L does not contain an even number
        """
        
        for n in L:
            if n % 2 == 0:
                return [n]
                # or just 'return n' if you want to return the number not within a list
        raise ValueError("No even numbers in L")