Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Try-except with NameError and TypeError

Can you please help me with the following. I am trying to catch two exceptions: 1) TypeError and 2)NameError. I use the following code below that estimates the average:

def calculate_average(number_list):
    try:
        if type(number_list) is not list:
            raise ValueError("You should pass list to this function")
    except ValueError as err:
        print(err)
        return
    try:
        average = sum(number_list)/len(number_list)
    
    except TypeError:
        print('List should contain numbers')
        return
    except NameError:
        print('List should contain numbers')
        return
 
    return average

The code works fine for:

print(calculate_average([1, 2, 3]))
print(calculate_average([1, 2, 'a']))

But when I use:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

print(calculate_average([1, 2, a]))

I have the following error that was supposed to be captured by except:

NameError: name 'a' is not defined

Can you please help me with understanding the issue? (I use Spyder)

>Solution :

The NameError on a is raised in the calling scope, not when you attempt to use number_list. You would need to catch it there:

try:
    print(calculate_average([1, 2, a]))
except NameError:
    print("Variable not defined")

However, you shouldn’t be catching NameErrors at all. When they arise in testing, you should figure out what undefined name you are trying to use, and make sure it is defined. Like most exceptions, this isn’t intended for flow control or dealing with easily fixed problems at runtime.


Rather than littering your code with run-time type check, consider using type hints and static typecheckers like mypy to catch code that would produce a TypeError at runtime.

# list[int] might be too restrictive, but this is a simplified
# example
def calculate_average(number_list: list[int]):
    
    average = sum(number_list)/len(number_list)
    return average

They only error left here that mypy wouldn’t catch is the attempt to divide by zero if you pass an empty list. That you can check for and handle. You can raise a ValueError, or just decide that the average of an empty list is 0 by definition.

def calculate_average(number_list: list[int]):
    if not number_list:
        # raise ValueError("Cannot average an empty list")
        return 0

    return sum(number_list)/len(number_list)

This is preferable to

try:
    return sum(number_list)/len(number_list)
except ZeroDivisionError:
    ...

because it anticipates the problem before you go to the trouble of calling sum and len.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading