【问题标题】:How to properly use python's isinstance() to check if a variable is a number?如何正确使用 python 的 isinstance() 检查变量是否为数字?
【发布时间】:2012-06-27 14:53:52
【问题描述】:

我发现一些旧的 Python 代码正在执行以下操作:

if type(var) is type(1):
   ...

正如预期的那样,pep8 抱怨 isinstance() 的这种推荐用法。

现在,问题是numbers 模块是在 Python 2.6 中添加的,我需要编写适用于 Python 2.5+ 的代码

所以if isinstance(var, Numbers.number) 不是解决方案。

在这种情况下,哪个是正确的解决方案?

【问题讨论】:

  • 如果你愿意使用 numpy,numpy.isfinite 应该可以解决问题。

标签: python python-2.5 pep8


【解决方案1】:

在 Python 2 中,您可以使用 types module:

>>> import types
>>> var = 1
>>> NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType)
>>> isinstance(var, NumberTypes)
True

注意使用元组来测试多种类型。

在后台,IntType 只是int 的别名,等等:

>>> isinstance(var, (int, long, float, complex))
True

complex 类型要求您的 python 编译时支持复数;如果您想对此进行防范,请使用 try/except 块:

>>> try:
...     NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType)
... except AttributeError:
...     # No support for complex numbers compiled
...     NumberTypes = (types.IntType, types.LongType, types.FloatType)
...

或者如果你直接使用类型:

>>> try:
...     NumberTypes = (int, long, float, complex)
... except NameError:
...     # No support for complex numbers compiled
...     NumberTypes = (int, long, float)
...

在 Python 3 中,types 不再有任何标准类型别名,complex 始终处于启用状态,并且不再存在 longint 的区别,因此在 Python 3 中始终使用:

NumberTypes = (int, float, complex)

最后但同样重要的是,您可以使用numbers.Numbers abstract base type(Python 2.6 中的新功能)来支持不直接从上述类型派生的自定义数字类型:

>>> import numbers
>>> isinstance(var, numbers.Number)
True

此检查还为 decimal.Decimal()fractions.Fraction() 对象返回 True

该模块确实假设启用了complex 类型;如果不是,您将收到导入错误。

【讨论】:

  • 看来numpy.int32 没有被int 捕获。
  • @MatthiasArras 它不是 Python int 类型的子类,不。但是,isinstance(np.int32(32), numbers.Integral) 是真的。
【解决方案2】:

Python 2 支持intfloatlongcomplexpython 3.x 四种数字类型,支持3:intfloatcomplex

>>> num = 10
>>> if isinstance(num, (int, float, long, complex)): #use tuple if checking against multiple types
      print('yes it is a number')

yes it is a number
>>> isinstance(num, float)   
False
>>> isinstance(num, int)
True
>>> a = complex(1, 2)
>>> isinstance(a, complex)
True

【讨论】:

    【解决方案3】:

    根据您在duck typing 中使用的内容,这可能是一种更好的方法(它是certainly commonly recommended)。 Martijn Pieters 方法的问题在于,您总是会错过列表中的某些类型的数字。在我的脑海中,您的代码将无法使用:sympy 有理数、任意精度整数和复数的任何实现。

    另一种方法是编写这样的函数:

    def is_number(thing):
        try:
            thing + 1
            return True
        except TypeError:
            return False
    

    此代码应适用于任何合理的数字实现。当然有一个主要缺点:它也适用于大量非数字的不合理实现(即,如果加号运算符被重载并接受整数)。

    另一种选择(取决于您为什么需要知道某事物是否为数字)是假设它是一个数字,如果不是,则代码中任何需要数字的位都会抛出错误。

    我并不是说这些方法总是更好(不像某些人......)只是因为它们值得考虑。

    【讨论】:

    • 我知道这已经很老了,但是如果thing 是布尔值,thing + 1 不会引发 TypeError。此外,如果事情是 numpy.nan,那么函数返回 True,这可能没有意义。
    • 我认为接受 nans 是合理的:虽然它是“not a number”的缩写,但它仍然是 float,它是一种数字类型。我所知道的大多数强类型语言都会在接受数字的地方使用 nans 进行编译。不过,operator+ 是为布尔值定义的,这很糟糕,我不知道。
    • ...肯定thing +1 会工作,如果thing 是任何 numpyscipy 数组,则不会引发任何异常,我怀疑这是理想的行为,如果有人想捕获var 是否类似于列表...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 2015-12-26
    • 2016-08-22
    • 2021-03-13
    相关资源
    最近更新 更多