用什么最python化的方法来检查一个对象是否是一个数字?

时间:2022-04-10 02:52:18

Given an arbitrary python object, what's the best way to determine whether it is a number? Here is is defined as acts like a number in certain circumstances.

给定一个任意的python对象,确定它是否是一个数字的最好方法是什么?这里的定义是在特定情况下的行为。

For example, say you are writing a vector class. If given another vector, you want to find the dot product. If given a scalar, you want to scale the whole vector.

例如,假设您正在编写一个向量类。如果给定另一个向量,你想求点积。如果给定一个标量,你想要缩放整个向量。

Checking if something is int, float, long, bool is annoying and doesn't cover user-defined objects that might act like numbers. But, checking for __mul__, for example, isn't good enough because the vector class I just described would define __mul__, but it wouldn't be the kind of number I want.

检查某个对象是否为int、float、long、bool,这很烦人,它不包括用户定义的对象,这些对象的行为可能与数字类似。但是,检查__mul__还不够好,因为我刚才描述的向量类将定义__mul__,但它不是我想要的那种数字。

11 个解决方案

#1


101  

Use Number from the numbers module to test isinstance(n, Number) (available since 2.6).

使用Number模块中的Number来测试isinstance(n, Number)(从2.6开始可用)。

>>> from numbers import Number
... from decimal import Decimal
... from fractions import Fraction
... for n in [2, 2.0, Decimal('2.0'), complex(2,0), Fraction(2,1), '2']:
...     print '%15s %s' % (n.__repr__(), isinstance(n, Number))
              2 True
            2.0 True
 Decimal('2.0') True
         (2+0j) True
 Fraction(2, 1) True
            '2' False

This is, of course, contrary to duck typing. If you are more concerned about how an object acts rather than what it is, perform your operations as if you have a number and use exceptions to tell you otherwise.

当然,这与duck typing相反。如果您更关心对象的行为而不是它是什么,那么就像您有一个数字一样执行操作,并使用异常来告诉您相反的情况。

#2


28  

You want to check if some object

你想要检查某个对象

acts like a number in certain circumstances

在某些情况下表现得像一个数字

If you're using Python 2.5 or older, the only real way is to check some of those "certain circumstances" and see.

如果您使用的是Python 2.5或更高版本,唯一的实际方法是检查某些“特定情况”并查看。

In 2.6 or better, you can use isinstance with numbers.Number -- an abstract base class (ABC) that exists exactly for this purpose (lots more ABCs exist in the collections module for various forms of collections/containers, again starting with 2.6; and, also only in those releases, you can easily add your own abstract base classes if you need to).

在2.6或更好的版本中,您可以使用isinstance和数字。Number—一个抽象基类(ABC),它正是为此目的而存在的(在集合模块中有很多ABC,用于各种形式的集合/容器,同样从2.6开始;而且,只有在这些版本中,如果需要的话,您可以轻松地添加自己的抽象基类)。

Bach to 2.5 and earlier, "can be added to 0 and is not iterable" could be a good definition in some cases. But, you really need to ask yourself, what it is that you're asking that what you want to consider "a number" must definitely be able to do, and what it must absolutely be unable to do -- and check.

Bach到2.5或更早,“可以添加到0且不可迭代”在某些情况下可能是一个很好的定义。但是,你真的需要问问自己,你想问的是,你想要考虑的“一个数字”一定能做什么,以及它绝对不能做什么——然后检查。

This may also be needed in 2.6 or later, perhaps for the purpose of making your own registrations to add types you care about that haven't already be registered onto numbers.Numbers -- if you want to exclude some types that claim they're numbers but you just can't handle, that takes even more care, as ABCs have no unregister method [[for example you could make your own ABC WeirdNum and register there all such weird-for-you types, then first check for isinstance thereof to bail out before you proceed to checking for isinstance of the normal numbers.Number to continue successfully.

这在2.6或更高版本中可能也需要,可能是为了让您自己的注册添加您所关心的尚未注册到数字上的类型。数字——如果你想排除一些类型声称他们数字但是你不能处理,这需要更多的关心,因为ABC没有注销方法[[例如你可以自己做ABC WeirdNum和注册所有这些weird-for-you类型,然后首先检查其isinstance纾困之前进行检查isinstance正常的数字。数量继续成功。

BTW, if and when you need to check if x can or cannot do something, you generally have to try something like:

顺便说一句,如果当你需要检查x是否能做某事或不能做某事时,你通常必须尝试以下方法:

try: 0 + x
except TypeError: canadd=False
else: canadd=True

The presence of __add__ per se tells you nothing useful, since e.g all sequences have it for the purpose of concatenation with other sequences. This check is equivalent to the definition "a number is something such that a sequence of such things is a valid single argument to the builtin function sum", for example. Totally weird types (e.g. ones that raise the "wrong" exception when summed to 0, such as, say, a ZeroDivisionError or ValueError &c) will propagate exception, but that's OK, let the user know ASAP that such crazy types are just not acceptable in good company;-); but, a "vector" that's summable to a scalar (Python's standard library doesn't have one, but of course they're popular as third party extensions) would also give the wrong result here, so (e.g.) this check should come after the "not allowed to be iterable" one (e.g., check that iter(x) raises TypeError, or for the presence of special method __iter__ -- if you're in 2.5 or earlier and thus need your own checks).

由于…的存在本身并不能说明什么有用的东西,因为……所有的序列都有它,以便与其他序列进行连接。这个检查等价于定义“一个数字是这样的东西,这样的东西序列是一个有效的单参数到builtin函数和”,例如。完全不可思议的类型(例如,将“错误”的异常归结为0,例如,一个ZeroDivisionError或ValueError &c)会传播异常,但是没关系,让用户知道这样的疯狂类型在好公司中是不可接受的;-);但是,“向量”的可和一个标量(Python标准库没有的,当然他们流行的第三方扩展)也会给出错误的结果,所以(举例来说)这张支票应该“不得iterable”后(例如,检查iter(x)提高TypeError,或存在的特殊方法__iter__——如果你在2.5或更早,因此需要自己检查)。

A brief glimpse at such complications may be sufficient to motivate you to rely instead on abstract base classes whenever feasible...;-).

只要稍微了解一下这些复杂的情况,就足以促使您在可行的情况下转而依赖抽象的基类。

#3


16  

This is a good example where exceptions really shine. Just do what you would do with the numeric types and catch the TypeError from everything else.

这是一个典型的例外情况。只需对数值类型执行您要执行的操作,并从其他所有类型中捕获类型错误。

But obviously, this only checks if a operation works, not whether it makes sense! The only real solution for that is to never mix types and always know exactly what typeclass your values belong to.

但显然,这只检查操作是否有效,而不检查操作是否有意义!唯一真正的解决方案是永远不要混合类型,并且始终准确地知道您的值属于什么类型的类。

#4


3  

To rephrase your question, you are trying to determine whether something is a collection or a single value. Trying to compare whether something is a vector or a number is comparing apples to oranges - I can have a vector of strings or numbers, and I can have a single string or single number. You are interested in how many you have (1 or more), not what type you actually have.

要重新表达您的问题,您正在尝试确定某物是集合还是单个值。试着比较一个东西是一个矢量还是一个数字在比较苹果和橘子——我可以有一个弦或数字的矢量,我可以有一个弦或一个数字。你感兴趣的是你有多少(1个或更多),而不是你实际拥有的类型。

my solution for this problem is to check whether the input is a single value or a collection by checking the presence of __len__. For example:

我对这个问题的解决方案是通过检查__len__的存在来检查输入是单个值还是一个集合。例如:

def do_mult(foo, a_vector):
    if hasattr(foo, '__len__'):
        return sum([a*b for a,b in zip(foo, a_vector)])
    else:
        return [foo*b for b in a_vector]

Or, for the duck-typing approach, you can try iterating on foo first:

或者,对于duck-typing方法,您可以尝试先在foo上迭代:

def do_mult(foo, a_vector):
    try:
        return sum([a*b for a,b in zip(foo, a_vector)])
    except TypeError:
        return [foo*b for b in a_vector]

Ultimately, it is easier to test whether something is vector-like than to test whether something is scalar-like. If you have values of different type (i.e. string, numeric, etc.) coming through, then the logic of your program may need some work - how did you end up trying to multiply a string by a numeric vector in the first place?

最终,测试一个东西是否像矢量要比测试一个东西是否像标量容易得多。如果您有不同类型的值(例如字符串、数字等)传入,那么程序的逻辑可能需要一些工作—您最初是如何尝试将一个字符串与一个数字向量相乘的?

#5


3  

Multiply the object by zero. Any number times zero is zero. Any other result means that the object is not a number (including exceptions)

把物体乘以0。任何数乘以0都是0。任何其他结果都意味着对象不是一个数字(包括异常)

def isNumber(x):
    try:
        return 0 == x*0
    except:
        return False

Using isNumber thusly will give the following output:

使用isNumber,输出如下:

class A: pass 

def foo(): return 1

for x in [1,1.4, A(), range(10), foo, foo()]:
    answer = isNumber(x)
    print '{answer} == isNumber({x})'.format(**locals())

Output:

输出:

True == isNumber(1)
True == isNumber(1.4)
False == isNumber(<__main__.A instance at 0x7ff52c15d878>)
False == isNumber([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
False == isNumber(<function foo at 0x7ff52c121488>)
True == isNumber(1)

There probably are some non-number objects in the world that define __mul__ to return zero when multiplied by zero but that is an extreme exception. This solution should cover all normal and sane code that you generate/encouter.

世界上可能有一些非数字对象定义__mul__当乘以0时返回0,但这是一个极端的例外。这个解决方案应该涵盖您生成/封装的所有正常的代码。

#6


2  

Probably it's better to just do it the other way around: You check if it's a vector. If it is, you do a dot product and in all other cases you attempt scalar multiplication.

也许用另一种方法来做更好:你检查它是否是一个向量。如果是,你做点积,在其他情况下你尝试标量乘法。

Checking for the vector is easy, since it should of your vector class type (or inherited from it). You could also just try first to do a dot-product, and if that fails (= it wasn't really a vector), then fall back to scalar multiplication.

检查向量很容易,因为它应该属于您的向量类类型(或者继承自它)。您也可以先尝试做点乘,如果失败(=它不是一个向量),那么就回到标量乘法。

#7


1  

Just to add upon. Perhaps we can use a combination of isinstance and isdigit as follows to find whether a value is a number (int, float, etc)

只是添加。也许我们可以使用isinstance和isdigit的组合来确定一个值是否是一个数字(int, float,等等)

if isinstance(num1, int) or isinstance(num1 , float) or num1.isdigit():

如果isinstance(num1, int)或isinstance(num1, float)或num1.isdigit():

#8


1  

To summarize / evaluate existing methods:

总结/评估现有方法:

Candidate    | type                      | delnan | mat | shrewmouse | ant6n
-------------------------------------------------------------------------
0            | <type 'int'>              |      1 |   1 |          1 |     1
0.0          | <type 'float'>            |      1 |   1 |          1 |     1
0j           | <type 'complex'>          |      1 |   1 |          1 |     0
Decimal('0') | <class 'decimal.Decimal'> |      1 |   0 |          1 |     1
True         | <type 'bool'>             |      1 |   1 |          1 |     1
False        | <type 'bool'>             |      1 |   1 |          1 |     1
''           | <type 'str'>              |      0 |   0 |          0 |     0
None         | <type 'NoneType'>         |      0 |   0 |          0 |     0
'0'          | <type 'str'>              |      0 |   0 |          0 |     1
'1'          | <type 'str'>              |      0 |   0 |          0 |     1
[]           | <type 'list'>             |      0 |   0 |          0 |     0
[1]          | <type 'list'>             |      0 |   0 |          0 |     0
[1, 2]       | <type 'list'>             |      0 |   0 |          0 |     0
(1,)         | <type 'tuple'>            |      0 |   0 |          0 |     0
(1, 2)       | <type 'tuple'>            |      0 |   0 |          0 |     0

(I came here by this question)

(我是通过这个问题来到这里的)

Code

#!/usr/bin/env python

"""Check if a variable is a number."""

import decimal


def delnan_is_number(candidate):
    import numbers
    return isinstance(candidate, numbers.Number)


def mat_is_number(candidate):
    return isinstance(candidate, (int, long, float, complex))


def shrewmouse_is_number(candidate):
    try:
        return 0 == candidate * 0
    except:
        return False


def ant6n_is_number(candidate):
    try:
        float(candidate)
        return True
    except:
        return False

# Test
candidates = (0, 0.0, 0j, decimal.Decimal(0),
              True, False, '', None, '0', '1', [], [1], [1, 2], (1, ), (1, 2))

methods = [delnan_is_number, mat_is_number, shrewmouse_is_number, ant6n_is_number]

print("Candidate    | type                      | delnan | mat | shrewmouse | ant6n")
print("-------------------------------------------------------------------------")
for candidate in candidates:
    results = [m(candidate) for m in methods]
    print("{:<12} | {:<25} | {:>6} | {:>3} | {:>10} | {:>5}"
          .format(repr(candidate), type(candidate), *results))

#9


0  

For the hypothetical vector class:

假设向量类:

Suppose v is a vector, and we are multiplying it by x. If it makes sense to multiply each component of v by x, we probably meant that, so try that first. If not, maybe we can dot? Otherwise it's a type error.

假设v是一个向量,我们把它乘以x,如果把v的每个分量乘以x有意义的话,我们可能是这个意思,所以先试试这个。如果没有,也许我们可以点?否则就是类型错误。

EDIT -- the below code doesn't work, because 2*[0]==[0,0] instead of raising a TypeError. I leave it because it was commented-upon.

编辑——下面的代码不起作用,因为2*[0]=[0,0]而不是引发一个类型错误。我离开它,因为它是被评论的。

def __mul__( self, x ):
    try:
        return [ comp * x for comp in self ]
    except TypeError:
        return [ x * y for x, y in itertools.zip_longest( self, x, fillvalue = 0 )

#10


0  

I had a similar issue, when implementing a sort of vector class. One way to check for a number is to just convert to one, i.e. by using

在实现某种向量类时,我遇到了类似的问题。检查一个数字的一种方法是把它转换成1,也就是使用

float(x)

This should reject cases where x cannot be converted to a number; but may also reject other kinds of number-like structures that could be valid, for example complex numbers.

这应该拒绝x不能转换成数字的情况;但也可能拒绝其他类型的类似数字的结构,比如复数。

#11


-1  

You could use the isdigit() function.

可以使用isdigit()函数。

>>> x = "01234"
>>> a.isdigit()
True
>>> y = "1234abcd"
>>> y.isdigit()
False

#1


101  

Use Number from the numbers module to test isinstance(n, Number) (available since 2.6).

使用Number模块中的Number来测试isinstance(n, Number)(从2.6开始可用)。

>>> from numbers import Number
... from decimal import Decimal
... from fractions import Fraction
... for n in [2, 2.0, Decimal('2.0'), complex(2,0), Fraction(2,1), '2']:
...     print '%15s %s' % (n.__repr__(), isinstance(n, Number))
              2 True
            2.0 True
 Decimal('2.0') True
         (2+0j) True
 Fraction(2, 1) True
            '2' False

This is, of course, contrary to duck typing. If you are more concerned about how an object acts rather than what it is, perform your operations as if you have a number and use exceptions to tell you otherwise.

当然,这与duck typing相反。如果您更关心对象的行为而不是它是什么,那么就像您有一个数字一样执行操作,并使用异常来告诉您相反的情况。

#2


28  

You want to check if some object

你想要检查某个对象

acts like a number in certain circumstances

在某些情况下表现得像一个数字

If you're using Python 2.5 or older, the only real way is to check some of those "certain circumstances" and see.

如果您使用的是Python 2.5或更高版本,唯一的实际方法是检查某些“特定情况”并查看。

In 2.6 or better, you can use isinstance with numbers.Number -- an abstract base class (ABC) that exists exactly for this purpose (lots more ABCs exist in the collections module for various forms of collections/containers, again starting with 2.6; and, also only in those releases, you can easily add your own abstract base classes if you need to).

在2.6或更好的版本中,您可以使用isinstance和数字。Number—一个抽象基类(ABC),它正是为此目的而存在的(在集合模块中有很多ABC,用于各种形式的集合/容器,同样从2.6开始;而且,只有在这些版本中,如果需要的话,您可以轻松地添加自己的抽象基类)。

Bach to 2.5 and earlier, "can be added to 0 and is not iterable" could be a good definition in some cases. But, you really need to ask yourself, what it is that you're asking that what you want to consider "a number" must definitely be able to do, and what it must absolutely be unable to do -- and check.

Bach到2.5或更早,“可以添加到0且不可迭代”在某些情况下可能是一个很好的定义。但是,你真的需要问问自己,你想问的是,你想要考虑的“一个数字”一定能做什么,以及它绝对不能做什么——然后检查。

This may also be needed in 2.6 or later, perhaps for the purpose of making your own registrations to add types you care about that haven't already be registered onto numbers.Numbers -- if you want to exclude some types that claim they're numbers but you just can't handle, that takes even more care, as ABCs have no unregister method [[for example you could make your own ABC WeirdNum and register there all such weird-for-you types, then first check for isinstance thereof to bail out before you proceed to checking for isinstance of the normal numbers.Number to continue successfully.

这在2.6或更高版本中可能也需要,可能是为了让您自己的注册添加您所关心的尚未注册到数字上的类型。数字——如果你想排除一些类型声称他们数字但是你不能处理,这需要更多的关心,因为ABC没有注销方法[[例如你可以自己做ABC WeirdNum和注册所有这些weird-for-you类型,然后首先检查其isinstance纾困之前进行检查isinstance正常的数字。数量继续成功。

BTW, if and when you need to check if x can or cannot do something, you generally have to try something like:

顺便说一句,如果当你需要检查x是否能做某事或不能做某事时,你通常必须尝试以下方法:

try: 0 + x
except TypeError: canadd=False
else: canadd=True

The presence of __add__ per se tells you nothing useful, since e.g all sequences have it for the purpose of concatenation with other sequences. This check is equivalent to the definition "a number is something such that a sequence of such things is a valid single argument to the builtin function sum", for example. Totally weird types (e.g. ones that raise the "wrong" exception when summed to 0, such as, say, a ZeroDivisionError or ValueError &c) will propagate exception, but that's OK, let the user know ASAP that such crazy types are just not acceptable in good company;-); but, a "vector" that's summable to a scalar (Python's standard library doesn't have one, but of course they're popular as third party extensions) would also give the wrong result here, so (e.g.) this check should come after the "not allowed to be iterable" one (e.g., check that iter(x) raises TypeError, or for the presence of special method __iter__ -- if you're in 2.5 or earlier and thus need your own checks).

由于…的存在本身并不能说明什么有用的东西,因为……所有的序列都有它,以便与其他序列进行连接。这个检查等价于定义“一个数字是这样的东西,这样的东西序列是一个有效的单参数到builtin函数和”,例如。完全不可思议的类型(例如,将“错误”的异常归结为0,例如,一个ZeroDivisionError或ValueError &c)会传播异常,但是没关系,让用户知道这样的疯狂类型在好公司中是不可接受的;-);但是,“向量”的可和一个标量(Python标准库没有的,当然他们流行的第三方扩展)也会给出错误的结果,所以(举例来说)这张支票应该“不得iterable”后(例如,检查iter(x)提高TypeError,或存在的特殊方法__iter__——如果你在2.5或更早,因此需要自己检查)。

A brief glimpse at such complications may be sufficient to motivate you to rely instead on abstract base classes whenever feasible...;-).

只要稍微了解一下这些复杂的情况,就足以促使您在可行的情况下转而依赖抽象的基类。

#3


16  

This is a good example where exceptions really shine. Just do what you would do with the numeric types and catch the TypeError from everything else.

这是一个典型的例外情况。只需对数值类型执行您要执行的操作,并从其他所有类型中捕获类型错误。

But obviously, this only checks if a operation works, not whether it makes sense! The only real solution for that is to never mix types and always know exactly what typeclass your values belong to.

但显然,这只检查操作是否有效,而不检查操作是否有意义!唯一真正的解决方案是永远不要混合类型,并且始终准确地知道您的值属于什么类型的类。

#4


3  

To rephrase your question, you are trying to determine whether something is a collection or a single value. Trying to compare whether something is a vector or a number is comparing apples to oranges - I can have a vector of strings or numbers, and I can have a single string or single number. You are interested in how many you have (1 or more), not what type you actually have.

要重新表达您的问题,您正在尝试确定某物是集合还是单个值。试着比较一个东西是一个矢量还是一个数字在比较苹果和橘子——我可以有一个弦或数字的矢量,我可以有一个弦或一个数字。你感兴趣的是你有多少(1个或更多),而不是你实际拥有的类型。

my solution for this problem is to check whether the input is a single value or a collection by checking the presence of __len__. For example:

我对这个问题的解决方案是通过检查__len__的存在来检查输入是单个值还是一个集合。例如:

def do_mult(foo, a_vector):
    if hasattr(foo, '__len__'):
        return sum([a*b for a,b in zip(foo, a_vector)])
    else:
        return [foo*b for b in a_vector]

Or, for the duck-typing approach, you can try iterating on foo first:

或者,对于duck-typing方法,您可以尝试先在foo上迭代:

def do_mult(foo, a_vector):
    try:
        return sum([a*b for a,b in zip(foo, a_vector)])
    except TypeError:
        return [foo*b for b in a_vector]

Ultimately, it is easier to test whether something is vector-like than to test whether something is scalar-like. If you have values of different type (i.e. string, numeric, etc.) coming through, then the logic of your program may need some work - how did you end up trying to multiply a string by a numeric vector in the first place?

最终,测试一个东西是否像矢量要比测试一个东西是否像标量容易得多。如果您有不同类型的值(例如字符串、数字等)传入,那么程序的逻辑可能需要一些工作—您最初是如何尝试将一个字符串与一个数字向量相乘的?

#5


3  

Multiply the object by zero. Any number times zero is zero. Any other result means that the object is not a number (including exceptions)

把物体乘以0。任何数乘以0都是0。任何其他结果都意味着对象不是一个数字(包括异常)

def isNumber(x):
    try:
        return 0 == x*0
    except:
        return False

Using isNumber thusly will give the following output:

使用isNumber,输出如下:

class A: pass 

def foo(): return 1

for x in [1,1.4, A(), range(10), foo, foo()]:
    answer = isNumber(x)
    print '{answer} == isNumber({x})'.format(**locals())

Output:

输出:

True == isNumber(1)
True == isNumber(1.4)
False == isNumber(<__main__.A instance at 0x7ff52c15d878>)
False == isNumber([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
False == isNumber(<function foo at 0x7ff52c121488>)
True == isNumber(1)

There probably are some non-number objects in the world that define __mul__ to return zero when multiplied by zero but that is an extreme exception. This solution should cover all normal and sane code that you generate/encouter.

世界上可能有一些非数字对象定义__mul__当乘以0时返回0,但这是一个极端的例外。这个解决方案应该涵盖您生成/封装的所有正常的代码。

#6


2  

Probably it's better to just do it the other way around: You check if it's a vector. If it is, you do a dot product and in all other cases you attempt scalar multiplication.

也许用另一种方法来做更好:你检查它是否是一个向量。如果是,你做点积,在其他情况下你尝试标量乘法。

Checking for the vector is easy, since it should of your vector class type (or inherited from it). You could also just try first to do a dot-product, and if that fails (= it wasn't really a vector), then fall back to scalar multiplication.

检查向量很容易,因为它应该属于您的向量类类型(或者继承自它)。您也可以先尝试做点乘,如果失败(=它不是一个向量),那么就回到标量乘法。

#7


1  

Just to add upon. Perhaps we can use a combination of isinstance and isdigit as follows to find whether a value is a number (int, float, etc)

只是添加。也许我们可以使用isinstance和isdigit的组合来确定一个值是否是一个数字(int, float,等等)

if isinstance(num1, int) or isinstance(num1 , float) or num1.isdigit():

如果isinstance(num1, int)或isinstance(num1, float)或num1.isdigit():

#8


1  

To summarize / evaluate existing methods:

总结/评估现有方法:

Candidate    | type                      | delnan | mat | shrewmouse | ant6n
-------------------------------------------------------------------------
0            | <type 'int'>              |      1 |   1 |          1 |     1
0.0          | <type 'float'>            |      1 |   1 |          1 |     1
0j           | <type 'complex'>          |      1 |   1 |          1 |     0
Decimal('0') | <class 'decimal.Decimal'> |      1 |   0 |          1 |     1
True         | <type 'bool'>             |      1 |   1 |          1 |     1
False        | <type 'bool'>             |      1 |   1 |          1 |     1
''           | <type 'str'>              |      0 |   0 |          0 |     0
None         | <type 'NoneType'>         |      0 |   0 |          0 |     0
'0'          | <type 'str'>              |      0 |   0 |          0 |     1
'1'          | <type 'str'>              |      0 |   0 |          0 |     1
[]           | <type 'list'>             |      0 |   0 |          0 |     0
[1]          | <type 'list'>             |      0 |   0 |          0 |     0
[1, 2]       | <type 'list'>             |      0 |   0 |          0 |     0
(1,)         | <type 'tuple'>            |      0 |   0 |          0 |     0
(1, 2)       | <type 'tuple'>            |      0 |   0 |          0 |     0

(I came here by this question)

(我是通过这个问题来到这里的)

Code

#!/usr/bin/env python

"""Check if a variable is a number."""

import decimal


def delnan_is_number(candidate):
    import numbers
    return isinstance(candidate, numbers.Number)


def mat_is_number(candidate):
    return isinstance(candidate, (int, long, float, complex))


def shrewmouse_is_number(candidate):
    try:
        return 0 == candidate * 0
    except:
        return False


def ant6n_is_number(candidate):
    try:
        float(candidate)
        return True
    except:
        return False

# Test
candidates = (0, 0.0, 0j, decimal.Decimal(0),
              True, False, '', None, '0', '1', [], [1], [1, 2], (1, ), (1, 2))

methods = [delnan_is_number, mat_is_number, shrewmouse_is_number, ant6n_is_number]

print("Candidate    | type                      | delnan | mat | shrewmouse | ant6n")
print("-------------------------------------------------------------------------")
for candidate in candidates:
    results = [m(candidate) for m in methods]
    print("{:<12} | {:<25} | {:>6} | {:>3} | {:>10} | {:>5}"
          .format(repr(candidate), type(candidate), *results))

#9


0  

For the hypothetical vector class:

假设向量类:

Suppose v is a vector, and we are multiplying it by x. If it makes sense to multiply each component of v by x, we probably meant that, so try that first. If not, maybe we can dot? Otherwise it's a type error.

假设v是一个向量,我们把它乘以x,如果把v的每个分量乘以x有意义的话,我们可能是这个意思,所以先试试这个。如果没有,也许我们可以点?否则就是类型错误。

EDIT -- the below code doesn't work, because 2*[0]==[0,0] instead of raising a TypeError. I leave it because it was commented-upon.

编辑——下面的代码不起作用,因为2*[0]=[0,0]而不是引发一个类型错误。我离开它,因为它是被评论的。

def __mul__( self, x ):
    try:
        return [ comp * x for comp in self ]
    except TypeError:
        return [ x * y for x, y in itertools.zip_longest( self, x, fillvalue = 0 )

#10


0  

I had a similar issue, when implementing a sort of vector class. One way to check for a number is to just convert to one, i.e. by using

在实现某种向量类时,我遇到了类似的问题。检查一个数字的一种方法是把它转换成1,也就是使用

float(x)

This should reject cases where x cannot be converted to a number; but may also reject other kinds of number-like structures that could be valid, for example complex numbers.

这应该拒绝x不能转换成数字的情况;但也可能拒绝其他类型的类似数字的结构,比如复数。

#11


-1  

You could use the isdigit() function.

可以使用isdigit()函数。

>>> x = "01234"
>>> a.isdigit()
True
>>> y = "1234abcd"
>>> y.isdigit()
False