如何检查我的Python对象是否为数字?

281

在Java中,所有数字类型都是从Number继承而来的,因此我会使用

(x instanceof Number).

Python的等效语句是什么?


1
并不是完全重复,另一个问题是这个问题的一个非常特定的情况(检查向量中的某个元素是否为数字),而且大多数得票最高的答案确实与该细节相关。 - jb.
1
将 x 乘以零。如果结果不是零,则 x 不是一个数字。请参见:https://dev59.com/1nA75IYBdhLWcg3wKlqM#44418960。 - shrewmouse
5个回答

335

测试您的变量是否是数字.Number的实例:

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

这使用 ABCs,适用于所有内置的数字类,以及如果它们值得一试(注册为Number ABC的子类)则适用于所有第三方类。

但是,在许多情况下,您不必手动检查类型-Python是 duck typed,混合某些兼容类型通常可以工作,但当某些操作没有意义时(4 -“1”),它将抛出错误消息,因此很少真正需要手动检查。这只是一个奖励。您可以在完成模块时添加它,以避免用实现细节麻烦他人。

这适用于从Python 2.6开始。在旧版本中,您基本上仅限于检查一些硬编码的类型。


13
当您传递一个布尔值时,这会产生错误的结果:isinstance(True, numbers.Number)返回True,即使True显然不是数字。 - Alex Kahn
4
在Python中,布尔值实际上就是数字:bool继承自intabs(True) == 1"foo" * False == ""sum([True, False, True]) == 2"%f" % True == "1.0"等等。 - user395760
13
令人沮丧的是,isinstance(float('nan'), numbers.Number)返回True - Nate
2
为了排除布尔值,您可以使用以下代码: isinstance(x, numbers.Number) and not isinstance(x, bool) - Scott
1
你也可以使用 type(x) in (int, float, complex) 来检查 x 是否直接属于这些类型之一,而不是它们的实例。 - Break
@Break 我认为你的意思是“直接检查 x 是否是这些类型之一的实例,而不是子类型的实例”。 - Stef

237

Python 3:

=>

Python 3:

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

Python 2:


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

请注意,对于Numpy对象,此答案的工作方式不正确。


2
谢谢,这是在Jython中为我工作的内容(它是python 2.5,因此没有'numbers'包)。 是的,我有一个真正的理由打破鸭子类型; 我需要不同地处理字符串和数字。 - Neal Ehardt
16
isinstance(Decimal(10), (int, long, float, complex))的结果是False - jpmc26
12
如果x是一个布尔值,这也不起作用。isinstance(True, (int, long, float, complex))将返回True - Alex Kahn
4
@AlexKahn isinstance(True, numbers.Number) 或者 isinstance(False, numbers.Number) 也会返回 True。 - nbro
3
简述:float('nan')可以被视为非数值,但这当然仍将返回True - Martin Thoma
显示剩余2条评论

62

使用numbers模块中的Number来测试isinstance(n, Number)是否成立(自2.6版本以来可用)。

isinstance(n, numbers.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

当然,这与鸭子类型相反。如果您更关心对象的行为而不是它的身份,请将操作视为具有数字并使用异常来告诉您其他情况。


14
“看看是否有异常”策略通常是无效的。Python在允许对各种非算术事物进行算术类型操作方面有些过于激进,因此仅仅因为一个对象允许使用 +* 并不意味着它与数字有任何相似之处。 - Tom Swirly

-1

当然你可以使用 isinstance,但请注意这不是 Python 的工作方式。Python 是一种鸭子类型语言。你不应该显式地检查你的类型。如果传递了不正确的类型,将会引发一个 TypeError

所以只要假设它是一个 int。不必费心检查。


1
正如之前所述,鸭子类型的整个重点在于允许在同一类中进行方法重载和方法多态。 - cowbert
3
鸭子类型并不总是最好的选择。有时,在函数开头放置一个小的检查段落并失败或修复输入要比将整个代码包含在 try-except 中更好,因为这会使整个代码难以阅读。 - Guimoute

-9

那不是 Python 的工作方式。只需像使用数字一样使用它,如果有人传递给您的不是数字,则失败。将正确的类型传递给函数是程序员的责任。


7
仅当它们被触发时才会生效。在“正常”情况下,它们比“if”语句更便宜。 - Tim Pietzcker
9
有时候情况并不总是那么简单,有时两种类型都支持接口,但你希望以不同的方式处理它们。想象一下一个应该将数字相加而不是连接字符串的 reduce 函数。 - Rob Young
17
假设脚本最为简单,不考虑复杂情况。正如Rob所说,有合理的需求将数字与字符串区分处理。在许多情况下,自定义类需要在乘以数字时表现出一种行为方式,在乘以其本身的实例时表现出另一种行为方式。例如您可能会这样实现一个矩阵类。 - Nerdmaster
5
@Falmarri 它确实如此...http://docs.python.org/2/reference/datamodel.html#emulating-numeric-types - Matt Luongo
4
防御式编程是必要的,尤其是当你使用这些值来执行数据操作时,比如在数据库中。动态语言很棒,但有时你需要保证。 - Chris
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接