309

In Java the numeric types all descend from Number so I would use

(x instanceof Number).

What is the python equivalent?

2
  • 2
    Not really a duplicate, the other one is a very specific case of this question (check if something is a number in a vector), and most voted answers really relate to that detail. Commented Jan 17, 2014 at 19:16
  • 1
    Multiply x by zero. if the results is anything other than zero then x is not a number see: stackoverflow.com/a/44418960/3419693 Commented Jun 7, 2017 at 17:16

5 Answers 5

360

Test if your variable is an instance of numbers.Number:

>>> import numbers
>>> import decimal
>>> [isinstance(x, numbers.Number) for x in (0, 0.0, 0j, decimal.Decimal(0))]
[True, True, True, True]

This uses ABCs and will work for all built-in number-like classes, and also for all third-party classes if they are worth their salt (registered as subclasses of the Number ABC).

However, in many cases you shouldn't worry about checking types manually - Python is duck typed and mixing somewhat compatible types usually works, yet it will barf an error message when some operation doesn't make sense (4 - "1"), so manually checking this is rarely really needed. It's just a bonus. You can add it when finishing a module to avoid pestering others with implementation details.

This works starting with Python 2.6. On older versions you're pretty much limited to checking for a few hardcoded types.

Sign up to request clarification or add additional context in comments.

6 Comments

This gives a false positive when you pass it a boolean: isinstance(True, numbers.Number) returns True even though True is clearly not a number.
@AlexKahn In Python, booleans are practically numbers: bool inherits from int, abs(True) == 1, "foo" * False == "", sum([True, False, True]) == 2, "%f" % True == "1.0", and so on.
Frustratingly, isinstance(float('nan'), numbers.Number) returns True
to exclude boolean you can use the following. isinstance(x, numbers.Number) and not isinstance(x, bool)
You can also use type(x) in (int, float, complex) to check if x is directly one of those types instead of an instance of them
|
251

Python 3:

isinstance(x, (int, float, complex)) and not isinstance(x, bool)

Python 2:

isinstance(x, (int, long, float, complex)) and not isinstance(x, bool)

Note that this answer works incorrectly for Numpy objects.

7 Comments

Thanks, this is what ended up working for me in Jython (which is python 2.5 so it doesn't have the 'numbers' package). And yes I have a real reason to break duck typing; I need to treat strings and numbers differently.
isinstance(Decimal(10), (int, long, float, complex)) gives False. -1
This also doesn't work if x is a boolean. isinstance(True, (int, long, float, complex)) returns True.
@AlexKahn isinstance(True, numbers.Number) or isinstance(False, numbers.Number) also returns True.
Short note: float('nan') might be considered non-numeric, but this will - of course - still return True.
|
65

Use Number from the numbers module to test isinstance(n, Number) (available since 2.6).

isinstance(n, numbers.Number)

Here it is in action with various kinds of numbers and one non-number:

>>> from numbers import Number
... from decimal import Decimal
... from fractions import Fraction
... for n in [2, 2.0, Decimal('2.0'), complex(2,0), Fraction(2,1), '2']:
...     print '%15s %s' % (n.__repr__(), isinstance(n, Number))
              2 True
            2.0 True
 Decimal('2.0') True
         (2+0j) True
 Fraction(2, 1) True
            '2' False

This is, of course, contrary to duck typing. If you are more concerned about how an object acts rather than what it is, perform your operations as if you have a number and use exceptions to tell you otherwise.

2 Comments

The "see if there's an exception" strategy is often ineffective. Python is a little aggressive in allowing arithmetic-type operations on all sorts of non-arithmetic things - so just because an object allows + or * doesn't mean it's anything at all like a number.
Won't this incorrectly report that True and False are numberrs?
-2

Sure you can use isinstance, but be aware that this is not how Python works. Python is a duck typed language. You should not explicitly check your types. A TypeError will be raised if the incorrect type was passed.

So just assume it is an int. Don't bother checking.

2 Comments

as noted before, the whole point of duck-typing is to allow method overloading and method polymorphism in the same class.
Duck-typing is not always the way to go. Sometimes it's better to have a small check paragraph at the start of a function and fail or fix inputs, rather than encase your whole code in try-except which makes the whole thing hard to read.
-16

That's not really how python works. Just use it like you would a number, and if someone passes you something that's not a number, fail. It's the programmer's responsibility to pass in the correct types.

7 Comments

...but only if they are triggered. In the "normal" case they are cheaper than an if statement.
not always quite so simple, sometimes both types support the interface but you want to handle them differently. Consider a reduce function that should add numbers but not concatenate strings.
This answer is assuming the most naive scripts, and doesn't consider complex cases. As Rob says, there are legitimate needs for handling a number differently than a string. There are also many cases where a custom class needs to behave one way when multiplied by a number and a different way when multiplied by an instance of itself. You might implement a matrix class in such a way.
@Falmarri it absolutely does... docs.python.org/2/reference/…
Defensive programming is a necessity especially when you are using those values to perform data manipulation operations in, for instance, a database. Dynamic languages are fantastic, but sometimes you need your guarantees.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.