一致的数字类型检查

4

让我们把鸭子留在池塘里。

为了明确,我正在使用Python 2.7.3。

我正在进行数字检查的操作,发现了一些奇怪的事情:

In [1]: numbers.Number.mro()
Out[1]: [numbers.Number, object]

In [2]: numbers.Complex.mro()
Out[2]: [numbers.Complex, numbers.Number, object]

In [3]: numbers.Real.mro()
Out[3]: [numbers.Real, numbers.Complex, numbers.Number, object]

In [4]: numbers.Rational.mro()
Out[4]: [numbers.Rational, numbers.Real, numbers.Complex,
         numbers.Number, object]

In [5]: numbers.Integral.mro()
Out[5]: [numbers.Integral, numbers.Rational, numbers.Real,
         numbers.Complex, numbers.Number, object]

我认为这种做法是有些逆向思维的,并且在 Python 本身内部存在一定的矛盾(如 intfloatcomplex 直接继承自 object):

In [6]: isinstance(int(), complex)
Out[6]: False

In [7]: isinstance(int(), numbers.Complex)
Out[7]: True

然后我写了以下函数:

def numeric_check(num):
    print "Is an int:", isinstance(num, int)
    print "Is a float:", isinstance(num, float)
    print "Is a complex:", isinstance(num, complex)
    print "Is a numbers.Number:", isinstance(num, numbers.Number)
    print "Is an numbers.Integer:", isinstance(num, numbers.Integral)
    print "Is a numbers.Real:", isinstance(num, numbers.Real)
    print "Is a numbers.Complex:", isinstance(num, numbers.Complex)
    print "Is a numpy.integer:", isinstance(num, numpy.integer)
    print "Is a numpy.floating:", isinstance(num, numpy.floating)
    print "Is a numpy.complex:", isinstance(num, numpy.complex)

并运行以下循环:

for dtype in [int, float, complex,
              numpy.int16, numpy.int32, numpy.int64,
              numpy.uint16, numpy.uint32, numpy.uint64,
              numpy.float16, numpy.float32, numpy.float64, numpy.complex64]:
    num = dtype()
    print dtype
    numeric_check(num)

以下是部分输出:

    类型 'int'
    是否为整型:True
    是否为浮点型:False
    是否为复数:False
    是否为 numbers.Number 类型:True
    是否为 numbers.Integer 类型:True
    是否为 numbers.Real 类型:True
    是否为 numbers.Complex 类型:True
    是否为 numpy.integer 类型:False
    是否为 numpy.floating 类型:False
    是否为 numpy.complex 类型:False

从上面的输出可以看出,intnumbers 模块中任何类型的一个实例。在我的电脑上,numpy 整型默认为 64 位,我们来看一下:

    类型 'numpy.int64'
    是否为整型:True
    是否为浮点型:False
    是否为复数:False
    是否为 numbers.Number 类型:True
    是否为 numbers.Integer 类型:True
    是否为 numbers.Real 类型:True
    是否为 numbers.Complex 类型:True
    是否为 numpy.integer 类型:True
    是否为 numpy.floating 类型:False
    是否为 numpy.complex 类型:False

它与 int 相同,并且额外通过了 numpy.integer。让我们检查一下 numpy.int16

    类型 'numpy.int16'
    是否为整型:False
    是否为浮点型:False
    是否为复数:False
    是否为 numbers.Number 类型:False
    是否为 numbers.Integer 类型:False
    是否为 numbers.Real 类型:False
    是否为 numbers.Complex 类型:False
    是否为 numpy.integer 类型:True
    是否为 numpy.floating 类型:False
    是否为 numpy.complex 类型:False

糟糕,它只通过了 numpy.integer。所以我的问题是:

  1. 这是斯巴达吗?
  2. numpy 部分的类型分离是一种设计选择吗?
  3. 除去鸭子类型,如果我想检查数字类型,最好忽略 numbers 模块,而改用以下方式吗?

类型检查:

isinstance(num, (int, numpy.integer)
isinstance(num, (float, numpy.floating)
isinstance(num, (complex, numpy.complex)
1个回答

5

数字中的类是抽象基类,您可以将numpy.int *注册为整数:

import numpy as np
import numbers
numbers.Integral.register(numpy.integer)
a = np.int16(100)
isinstance(a, numbers.Integral)

但是numpy.int16的范围比int小,如果你使用numpy.int16进行计算,可能会导致溢出。


我之前不知道寄存器的功能,这真的很方便。然而,numbers 类的 MRO(方法解析顺序)似乎有些奇怪。从数学的角度来看,我可以理解整数可能是特定的有理数、实数或复数,但从编程的角度来看,MRO似乎并没有帮助到我。因此,如果我想检查一个数字的类型,我首先要检查它是否为复数,然后是实数,接着是有理数,最后才是整数。 - Midnighter

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