checking if python object can be interpreted as real number [python]

2.1k Views Asked by At

I wrote the function in python:

def is_number_like(x):
     try:
        int(x) + 1
    except:
        return False
    return True

is there any difference if I write float(x) or int(x)? Or could + 1 part be useful in some case?

EDIT: is_number_like will return True when string is passed - that is what I don't want to be. I would like a function which will return False anytime a text-like value is passed as an argument. Is there a method for this?

maybe:

def is_number_like(x):
     try:
        x + 1
    except:
        return False
    return True

will be better?

or maybe:

def is_number_like(x):
     try:
        float(x + 1) == float(x) + 1
    except:
        return False
    return True

I want to write a module which would accept any well-behaved number type which represents one dimensional real number (for example SimpleITK.sitkUInt8 number type or numpy.int32 and so on...).

I'm afraid that there could be libraries, which will not throw an error in casting to int or float. For example I can imagine situation like this:

>>> z = SomeComplexType(1. + 2.j)
>>> z
(1+2j)
>>> z -= 2.j
>>> z
(1+0j)
>>> float(z) # does not raise an error
1.

is this possible, should I worry about such situation?

And do all well designed real number types will cast to float without an error?

ps. i have read this already: How do I check if a string is a number (float)?

4

There are 4 best solutions below

3
On BEST ANSWER

If I understand correctly, what you're actually trying to do is find out whether an object behaves in "number"-like ways (e.g. can you append +1 to it). If so, there's an easier way:

>>> from numbers import Number
>>> 
>>> my_complex_number = 3-2j
>>> my_stringy_number = "3.14"
>>>
>>> isinstance(my_complex_number, Number)
True
>>> isinstance(my_stringy_number, Number)
False
7
On

There is a difference between float(..) and int(..).

float(..) will try to parse a string or any object that has a __float__ method. For example int, float and complex have a __float__ method. You can define such method for a custom class as well.

If you aim to convert a complex number to a float(..), it will error:

>>> float(2+2j)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float

The result of a float(..) function is guaranteed to be a float: if the __float__ method returns a non-float value, it will raise a TypeError:

>>> class Foo:
...     def __float__(self):
...         return 2j
... 
>>> float(Foo())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __float__ returned non-float (type complex)

So a simply float(..) try is sufficient:

def is_number_like(x):
     try:
        float(x)
        return True
    except TypeError, ValueError:
        return False

Most numeric-like types in Python (like the numpy.int16) **support such __float__ method.

int(..) on the other hand works with a string and with the __int__ method. Again if you call int(..), the result is guaranteed to be an int.

So in , you could use two checks: one for float(..) and one for int(..):

def is_number_like(x):
     try:
        int(x)
        return True
    except TypeError, ValueError:
        try:
            float(x)
            return True
        except TypeError, ValueError:
            return False

Or if you want to return the number-like object:

def is_number_like(x):
     try:
        return int(x)
    except TypeError:
        try:
            return float(x)
        except TypeError:
            return None

(this will return None if both attempts fail).

Mind that in , there is also a long type (and guess what, it works with __long__).

5
On

In python complex numbers can't be directly converted to int nor float this would raise a TypeError: can't convert complex to....

Any other object than an "int or float convertible" one will raise a ValueError.

To make an object from a custom class "convertible" one will have to define the appropriate "dunders" __int__ and __float__, see doc

So a function that check if a object can be cast as a real number you can do this:

def is_real_number(number):
    try:
        int(number)
    except TypeError, ValueError:
        return False
    return True
3
On

Why not just use

any([isinstance(x, t) for t in [float, int, complex]])

You can modify the list of types to be whatever you need it to be.