python-3.xassertboolean-expression

What is a good way to verify if arguments of a function are numbers


I have a function which takes in 3 arguments and I want to make sure those three arguments are numbers.

As of right now, I've made this after a bit of experimenting and it seems to work but I'm not sure since I don't really understand the priority/precedence of boolean operators

assert type(x)==type(y)==type(z) in (int, float), "Please provide numbers"

What I'm looking for is:


Solution

  • All comparison operators (including the membership operator) have the same precedence in Python and have a left-to-right chaining, so your chained comparisons would be equivalent (with the difference that expressions are evaluated more than once if you don't chain) to:

    (type(x) == type(y)) and (type(y) == type(z)) and (type(z) in (int, float)).
    

    Since they all have the same precedence, the order of evaluation is left to right.

    The main problem with this is that if you want to allow some arguments to be integers and others to be floats, they will not be validated:

    >>> x, y, z = 3, 2.1, 7
    >>> assert type(x)==type(y)==type(z) in (int, float), "Please provide numbers"
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AssertionError: Please provide numbers
    

    If mixing arguments with both types is valid, you will have to modify your condition. An obvious choice is to use type(arg) in (int, float) for all arguments.

    On the other hand, isinstance is often used instead of type because it allow instances of subclasses to be validated as well, which is usually the norm.

    assert isinstance(x, (int, float)) and isinstance(y, (int, float)) and isinstance(z, (int, float)), "Please provide numbers".
    

    Or more concise:

    assert all(isinstance(arg, (int, float)) for arg in (x, y, z)), "Please provide numbers".