Let's leave the ducks in the pond.
Just to make it clear, I'm working with Python 2.7.3.
I was playing with number checks and came across a few things that I found odd:
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]
This strikes me as... counter-productive and is somewhat contradictory within Python itself (int
, float
, complex
just inherit from object
directly):
In [6]: isinstance(int(), complex)
Out[6]: False
In [7]: isinstance(int(), numbers.Complex)
Out[7]: True
Then I wrote the following function:
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)
And ran the following loop:
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)
I'll spare you the full output but a few excerpts:
type 'int'
Is an int: True
Is a float: False
Is a complex: False
Is a numbers.Number: True
Is an numbers.Integer: True
Is a numbers.Real: True
Is a numbers.Complex: True
Is a numpy.integer: False
Is a numpy.floating: False
Is a numpy.complex: False
So as can be expected from the above, int
is an instance of any type in the numbers
module. On my machine the default numpy
integer is 64bit, let's take a look:
type 'numpy.int64'
Is an int: True
Is a float: False
Is a complex: False
Is a numbers.Number: True
Is an numbers.Integer: True
Is a numbers.Real: True
Is a numbers.Complex: True
Is a numpy.integer: True
Is a numpy.floating: False
Is a numpy.complex: False
It matches the same types as int
and additionally passes as a numpy.integer
. Let's check a numpy.int16
:
type 'numpy.int16'
Is an int: False
Is a float: False
Is a complex: False
Is a numbers.Number: False
Is an numbers.Integer: False
Is a numbers.Real: False
Is a numbers.Complex: False
Is a numpy.integer: True
Is a numpy.floating: False
Is a numpy.complex: False
Ouch, it only passes as a numpy.integer
. So my questions:
- Is this Sparta?
- Is the type separation of the
numpy
part a design choice? - Duck typing aside, if I wanted to check numeric types am I best off ignoring the
numbers
module and instead doing the following?
Type checks:
isinstance(num, (int, numpy.integer)
isinstance(num, (float, numpy.floating)
isinstance(num, (complex, numpy.complex)
the classes in numbers are Abstract Base Classes, you can register numpy.int* as Integral:
import numpy as np
import numbers
numbers.Integral.register(numpy.integer)
a = np.int16(100)
isinstance(a, numbers.Integral)
But the range of numpy.int16 is smaller than int, if you do calculation with numpy.int16, overflow may occurred.
Let's leave the ducks in the pond.
Just to make it clear, I'm working with Python 2.7.3.
I was playing with number checks and came across a few things that I found odd:
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]
This strikes me as... counter-productive and is somewhat contradictory within Python itself (int
, float
, complex
just inherit from object
directly):
In [6]: isinstance(int(), complex)
Out[6]: False
In [7]: isinstance(int(), numbers.Complex)
Out[7]: True
Then I wrote the following function:
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)
And ran the following loop:
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)
I'll spare you the full output but a few excerpts:
type 'int'
Is an int: True
Is a float: False
Is a complex: False
Is a numbers.Number: True
Is an numbers.Integer: True
Is a numbers.Real: True
Is a numbers.Complex: True
Is a numpy.integer: False
Is a numpy.floating: False
Is a numpy.complex: False
So as can be expected from the above, int
is an instance of any type in the numbers
module. On my machine the default numpy
integer is 64bit, let's take a look:
type 'numpy.int64'
Is an int: True
Is a float: False
Is a complex: False
Is a numbers.Number: True
Is an numbers.Integer: True
Is a numbers.Real: True
Is a numbers.Complex: True
Is a numpy.integer: True
Is a numpy.floating: False
Is a numpy.complex: False
It matches the same types as int
and additionally passes as a numpy.integer
. Let's check a numpy.int16
:
type 'numpy.int16'
Is an int: False
Is a float: False
Is a complex: False
Is a numbers.Number: False
Is an numbers.Integer: False
Is a numbers.Real: False
Is a numbers.Complex: False
Is a numpy.integer: True
Is a numpy.floating: False
Is a numpy.complex: False
Ouch, it only passes as a numpy.integer
. So my questions:
- Is this Sparta?
- Is the type separation of the
numpy
part a design choice? - Duck typing aside, if I wanted to check numeric types am I best off ignoring the
numbers
module and instead doing the following?
Type checks:
isinstance(num, (int, numpy.integer)
isinstance(num, (float, numpy.floating)
isinstance(num, (complex, numpy.complex)
the classes in numbers are Abstract Base Classes, you can register numpy.int* as Integral:
import numpy as np
import numbers
numbers.Integral.register(numpy.integer)
a = np.int16(100)
isinstance(a, numbers.Integral)
But the range of numpy.int16 is smaller than int, if you do calculation with numpy.int16, overflow may occurred.
0 commentaires:
Enregistrer un commentaire