检查对象是否为数字的最pythonic方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3441358/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the most pythonic way to check if an object is a number?
提问by Claudiu
Given an arbitrary python object, what's the best way to determine whether it is a number? Here isis defined as acts like a number in certain circumstances.
给定一个任意的 python 对象,确定它是否是数字的最佳方法是什么?这里is定义为acts like a number in certain circumstances。
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, boolis 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__,但它不会是我想要的那种数字。
采纳答案by Steven Rumbalski
Use Numberfrom the numbersmodule to test isinstance(n, Number)(available since 2.6).
Number从numbers模块中使用以进行测试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(f'{n!r:>14} {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 actsrather than what it is, perform your operations as if you have a number and use exceptions to tell you otherwise.
当然,这与鸭子类型相反。如果您更关心对象的行为方式而不是它是什么,请执行您的操作,就像您有一个数字一样,并使用异常来告诉您其他情况。
回答by Jochen Ritzel
This is a good example where exceptions really shine. Just do what you would do with the numeric types and catch the TypeErrorfrom everything else.
这是一个很好的例子,异常真正闪耀。只需执行您对数字类型所做的操作,然后TypeError从其他所有类型中捕获。
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.
但显然,这只检查操作是否有效,而不是检查是否有意义!唯一真正的解决方案是永远不要混合类型,并始终确切地知道您的值属于哪个类型类。
回答by sth
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.
检查向量很容易,因为它应该属于您的向量类类型(或从它继承)。你也可以先尝试做一个点积,如果失败(=它不是一个真正的向量),然后回到标量乘法。
回答by Katriel
For the hypothetical vector class:
对于假设的向量类:
Suppose vis a vector, and we are multiplying it by x. If it makes sense to multiply each component of vby x, we probably meant that, so try that first. If not, maybe we can dot? Otherwise it's a type error.
假设v是一个向量,我们将它乘以x。如果将vby 的每个分量相乘是有意义的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]不是提高TypeError. 我离开它是因为它被评论了。
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 )
回答by Alex Martelli
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 isinstancewith numbers.Number-- an abstract base class (ABC) that exists exactly for this purpose (lots more ABCs exist in the collectionsmodule 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与numbers.Number 一起使用——一个抽象基类 (ABC) 正是为此目的而存在的(collections模块中存在更多 ABC,用于各种形式的集合/容器,再次从 2.6 开始;并且,也仅在这些版本中,您可以根据需要轻松添加自己的抽象基类)。
Bach to 2.5 and earlier,
"can be added to 0and 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 unableto 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 excludesome types that claim they're numbers but you just can't handle, that takes even more care, as ABCs have no unregistermethod [[for example you could make your own ABC WeirdNumand register there all such weird-for-you types, then first check for isinstancethereof to bail out before you proceed to checking for isinstanceof the normal numbers.Numberto continue successfully.
这在 2.6 或更高版本中也可能需要,也许是为了进行自己的注册以添加您关心但尚未注册的类型numbers.Numbers- 如果您想排除某些声称它们是数字但您只是无法处理,这需要更加小心,因为 ABC 没有任何unregister方法 [[例如,您可以制作自己的 ABCWeirdNum并在那里注册所有这些对您来说很奇怪的类型,然后isinstance在继续之前先检查它们以退出检查isinstance正常numbers.Number以继续成功。
BTW, if and when you need to check if xcan 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 ZeroDivisionErroror 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 afterthe "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).
__add__本身的存在告诉你没有任何用处,因为例如所有序列都有它用于与其他序列连接的目的。例如,此检查等效于定义“一个数字是这样的东西,这样的东西的序列是内置函数的有效单个参数sum”。完全奇怪的类型(例如,当总和为 0 时引发“错误”异常的类型,例如 aZeroDivisionError或ValueError&c)将传播异常,但没关系,尽快让用户知道这种疯狂的类型是不可接受的公司;-); 但是,可以总结为标量的“向量”(Python 的标准库没有,但当然它们作为第三方扩展很受欢迎)也会在这里给出错误的结果,所以(例如“不允许迭代”一个(例如,检查iter(x)raises 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...;-).
对这些复杂情况的简要介绍可能足以激励您在可行的情况下转而依赖抽象基类......;-)。
回答by shadab.tughlaq
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():
回答by Ant6n
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
在实现某种矢量类时,我遇到了类似的问题。检查数字的一种方法是转换为一个,即使用
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 不能转换为数字的情况;但也可能拒绝其他可能有效的类似数字的结构,例如复数。
回答by Gordon Bean
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 foofirst:
或者,对于鸭子类型的方法,您可以先尝试迭代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?
归根结底,测试某事物是否类似向量比测试某事物是否类似标量更容易。如果您有不同类型的值(即字符串、数字等),那么您的程序逻辑可能需要一些工作 - 您最初是如何尝试将字符串乘以数字向量的?
回答by shrewmouse
Multiply the object by zero. Any number times zero is zero. Any other result means that the object is not a number (including exceptions)
将对象乘以零。任何数字乘以零都是零。任何其他结果表示对象不是数字(包括异常)
def isNumber(x):
try:
return bool(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 normaland sanecode that you generate/encouter.
世界上可能有一些非数字对象定义__mul__在乘以零时返回零,但这是一个极端的例外。此解决方案应涵盖您生成/遇到的所有正常和健全的代码。
numpy.array example:
numpy.array 示例:
import numpy as np
def isNumber(x):
try:
return bool(x*0 == 0)
except:
return False
x = np.array([0,1])
answer = isNumber(x)
print('{answer} == isNumber({x})'.format(**locals()))
output:
输出:
False == isNumber([0 1])
回答by rsy
You could use the isdigit() function.
您可以使用 isdigit() 函数。
>>> x = "01234"
>>> a.isdigit()
True
>>> y = "1234abcd"
>>> y.isdigit()
False

