在python中,如何检查变量是否为数值类型且具有有意义的值?
这里我指的是数字类型'像int
,float
和complex
那些具有不同位长度和有意义值的'它不是nan
或任何其他不能用于进一步计算的特殊值。
(我想这是一个很常见的问题,必须有一个重复的问题,但我没有在快速搜索后找到一个。如果有重复,请告诉我。)
答案 0 :(得分:1)
>>> from math import isnan
>>> isnan(float('nan'))
True
>>> isnan(1j.real)
False
>>> isnan(1j.imag)
False
整数永远不会是NaN。
答案 1 :(得分:1)
Python 2.x和3.x
import math
import numbers
def is_numerical(x):
return isinstance(x, numbers.Number) and not isinstance(x, bool) and not math.isnan(abs(n)) and math.isfinite(abs(n))
区别的原因是因为Python 3将long
和int
类型合并为int
。
编辑:使用numbers.Number
添加以下答案,以排除布尔值。
答案 2 :(得分:1)
这取决于你想要多么彻底。除了内置类型(complex
,float
和int
)之外,还有其他类型在python中被视为数字。例如:fractions.Fraction
,decimal.Decimal
甚至bool
都可以作为一个数字。然后,您将获得具有自己的数字类型的外部库。到目前为止,最大的是numpy
。使用numpy
某些类型将成功isinstance
检查,而其他类型则不会。例如:isinstance(numpy.float64(10), float)
为真,但isinstance(numpy.float32(10), float)
不是。
除此之外,你甚至可以拥有一个用户定义的类,它就像一个数字。
Python确实提供了解决此问题的一种方法 - numbers
模块。它提供了几种表示不同类型数字的抽象类型。任何实现数字功能的类都可以将自身注册为与相关类型兼容。 numbers.Number
是最基本的,因此也是您正在寻找的。您所要做的就是在isinstance
检查中使用它。例如
from numbers import Number
from decimal import Decimal
from fractions import Fraction
import numpy
assert isinstance(1, Number)
assert isinstance(1.5, Number)
assert isinstance(1+5j, Number)
assert isinstance(True, Number)
assert isinstance(Decimal("1.23"), Number)
assert isinstance(Fraction(1, 2), Number)
assert isinstance(numpy.float64(10), Number)
assert isinstance(numpy.float32(10), Number)
assert isinstance(numpy.int32(10), Number)
assert isinstance(numpy.uint32(10), Number)
这仍然让我们不知道对象是否实际上是一个数字,而不是"而不是数字"。 math.isnan
函数对此有好处,但它要求数字可以转换为float(不是所有数字都是)。这里的一个大问题是complex
类型。有几种方法可以解决这个问题:使用abs
进行额外的isinstance
检查(但这有其自身令人头疼的问题)或测试是否相等。
abs
可用于每种数字类型(我能想到)。对于大多数数字,它返回数字的正数,但对于复数,它返回其数量(浮点数)。所以现在我们可以做isnan
检查。 nan
也是一个特殊数字,因为它是唯一与自身不相等的数字。
这意味着您的最终检查可能如下:
import math
import numbers
def number_is_not_nan(n):
return isinstance(n, numbers.Number) and not math.isnan(abs(n))
def number_is_finite(n):
return isinstance(n, numbers.Number) and not math.isfinite(abs(n))
答案 3 :(得分:-1)
我正在回答我自己的问题。这是基于Seth Michael Larson's answer
和DaveTheScientist's answer for another question。考虑到我需要小心float('inf')
和float('-inf')
以及float('nan')
,并且传递的参数x
可能很复杂,我最后编写了以下函数检查。
def is_a_meaningful_number(x):
import math
if sys.version_info >= (3, 0, 0):
NUMERIC_TYPES = (int, complex, float)
else:
NUMERIC_TYPES = (int, long, complex, float)
return isinstance(x, NUMERIC_TYPES) and float('-inf') < abs(x) < float('inf')