276

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

(x instanceof Number).

What is the python equivalent?

MERose
  • 4,048
  • 7
  • 53
  • 79
Neal Ehardt
  • 10,334
  • 9
  • 41
  • 51
  • 1
    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. – jb. Jan 17 '14 at 19:16
  • 1
    Multiply x by zero. if the results is anything other than zero then x is not a number see: https://stackoverflow.com/a/44418960/3419693 – shrewmouse Jun 07 '17 at 17:16

5 Answers5

330

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.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
  • 12
    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. – Alex Kahn Nov 24 '15 at 21:34
  • 4
    @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. –  Nov 24 '15 at 22:12
  • 12
    Frustratingly, ```isinstance(float('nan'), numbers.Number)``` returns ```True``` – Nate Apr 30 '18 at 19:31
  • 2
    to exclude boolean you can use the following. `isinstance(x, numbers.Number) and not isinstance(x, bool)` – Scott Dec 03 '19 at 02:39
  • 1
    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 – Break Feb 06 '21 at 21:08
  • @Break I think you mean "to check if x is an instance of one of these types directly instead of an instance of a child type". – Stef Feb 09 '23 at 16:20
234

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.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Matt
  • 4,849
  • 3
  • 26
  • 23
  • 2
    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. – Neal Ehardt Nov 15 '10 at 18:45
  • 15
    `isinstance(Decimal(10), (int, long, float, complex))` gives `False`. -1 – jpmc26 Dec 16 '14 at 18:05
  • 11
    This also doesn't work if `x` is a boolean. `isinstance(True, (int, long, float, complex))` returns `True`. – Alex Kahn Nov 24 '15 at 21:28
  • 4
    @AlexKahn `isinstance(True, numbers.Number)` or `isinstance(False, numbers.Number)` also returns True. – nbro Feb 13 '17 at 21:16
  • `True` and `False` are integers in python (boolean is a subclass of int). Do another check: `type(True) is boolean` – Epic Wink May 08 '17 at 02:39
  • 3
    Short note: `float('nan')` might be considered non-numeric, but this will - of course - still return `True`. – Martin Thoma Oct 15 '18 at 21:03
  • 1
    numpy gotcha: `isinstance(np.int64, int) == False` – olejorgenb Mar 09 '21 at 23:40
62

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.

Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
  • 14
    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. – Tom Swirly May 07 '16 at 13:59
0

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.

user225312
  • 126,773
  • 69
  • 172
  • 181
  • as noted before, the whole point of duck-typing is to allow method overloading and method polymorphism in the same class. – cowbert Oct 05 '17 at 22:13
  • 2
    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. – Guimoute Nov 25 '19 at 14:41
-8

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.

Falmarri
  • 47,727
  • 41
  • 151
  • 191
  • Specifically, use `except TypeError:`. Exceptions are relatively expensive, however. – JAL Nov 15 '10 at 17:43
  • 7
    ...but only if they are triggered. In the "normal" case they are cheaper than an `if` statement. – Tim Pietzcker Nov 15 '10 at 17:51
  • 9
    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. – Rob Young Apr 20 '11 at 13:49
  • 17
    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. – Nerdmaster Feb 04 '12 at 14:06
  • @Nerdmaster: Python specifically doesn't support operator overloading. – Falmarri Feb 06 '12 at 05:19
  • 5
    @Falmarri it absolutely does... http://docs.python.org/2/reference/datamodel.html#emulating-numeric-types – Matt Luongo Jan 04 '13 at 04:18
  • 4
    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. – Chris Aug 12 '14 at 14:33