raising ValueError in a for loop

Viewed 37

I am new to coding so bear with me. I am making a function that counts how many trues are in a list that is later defined. I also need a ValueError for incorrect input types. It also has to be a for loop. Please tell me what I am going wrong.


def only_true(bool_list):
    trues_count = 0
    for value in bool_list:
        if value == int or value == float:
            if value == True:
                trues_count = trues_count + 1   
        raise ValueError("values in list must be True or False")
    return trues_count

2 Answers

Since bool is a subclass of int, you can simply add value to true_count. True will return 1 for arithmetic operations, whereas False will return 0.

Remember also to first check that the type is a bool, and raise an error as needed.

def only_true(bool_list: list):
    trues_count = 0

    for value in bool_list:
        if not isinstance(value, bool):
            raise ValueError("values in list must be True or False")

        trues_count += value

    return trues_count

print(only_true([False, False, True, False, True]))  # 2

# raises a ValueError
# only_true([1])

Below is a slightly different way of looking at it, where we check if value is True or False explicitly. If a value is not one of (True, False), then it follows it is not a bool.

def only_true(bool_list: list):
    trues_count = 0

    for value in bool_list:
        if value is True:
            trues_count += 1
        elif value is not False:
            # if a value is not True or False, then
            # by definition it is not a `bool`.
            raise ValueError("values in list must be True or False")

    return trues_count

Here is arguably a more "elegant" solution:

def _handle_err(e):
    raise ValueError(f"{e!r}: values in list must be True or False, not {type(e).__name__}")


def only_true(bool_list: list):
    return sum(v if isinstance(v, bool) else _handle_err(v) for v in bool_list)

Lastly, this one liner will return the number of True (or truthy) values in a list, without explicitly checking that each element is a bool type.

only_true = sum

Your code is very close to correct. To determine the type of a variable you should use the type() function instead of comparing the value of the variable to a type such as int or float. In addition, I fixed your nested conditional so that we first check for a type mismatch then we check to see how many "trues" there are.

def only_true(bool_list):
    trues_count = 0
    for value in bool_list:
        if type(value) != bool:
            raise ValueError("values in list must be True or False")

        if value:
            trues_count = trues_count + 1   
        
    return trues_count

print(only_true([True, False, False, True]))
print(only_true([True, False, False, True, 1]))

Output

2
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    print(only_true([True, False, False, True, 1]))
  File "test.py", line 5, in only_true
    raise ValueError("values in list must be True or False")
ValueError: values in list must be True or False
Related