如何正确使用python的isinstance()来检查变量是否是数字?

时间:2012-06-26 09:53:33

标签: python python-2.5 pep8

我发现了一些旧代的Python代码:

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

正如预期的那样,pep8抱怨推荐使用isinstance()

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

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

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

3 个答案:

答案 0 :(得分:98)

在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始终处于启用状态且不再存在long vs int差异,因此在Python 3中总是使用:

NumberTypes = (int, float, complex)

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

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

此检查还会返回Truedecimal.Decimal()个对象的fractions.Fraction()

该模块确实假设complex类型已启用;如果不是,你会得到导入错误。

答案 1 :(得分:18)

Python 2支持四种类型的数字intfloatlongcomplex以及python 3.x支持3:int,{{ 1}}和float

complex

答案 2 :(得分:3)

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

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

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

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

另一种选择(取决于你需要知道某些东西是否为数字的原因)只是假设它是一个数字,如果不是错误,那么代码中的任何一位都需要一个数字。

我不是说这些方法总是更好(不像有些人......)只是他们值得考虑。