检查对象是否为数字的最pythonic方法是什么?

新手上路,请多包涵

给定一个任意的 python 对象,确定它是否为数字的最佳方法是什么?这里 is 被定义为 acts like a number in certain circumstances

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

Checking if something is int , float , long , bool is annoying and doesn’t cover user-defined objects that might act like数字。但是,例如,检查 __mul__ 还不够好,因为我刚才描述的向量类会定义 __mul__ ,但它不是我想要的那种数字。

原文由 Claudiu 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 328
2 个回答

使用 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

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

原文由 Steven Rumbalski 发布,翻译遵循 CC BY-SA 4.0 许可协议

你想检查一些对象

在某些情况下就像一个数字

如果您使用的是 Python 2.5 或更早版本,唯一真正的方法是检查其中一些“特定情况”并查看。

在 2.6 或更高版本中,您可以将 isinstancenumbers.Number 一起使用 - 一个抽象基类 (ABC) 正是为此目的而存在的(在 collections 模块中存在更多的 ABC)各种形式的集合/容器,再次从 2.6 开始;而且,也只有在那些版本中,如果需要,您可以轻松添加自己的抽象基类)。

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

这可能在 2.6 或更高版本中也需要,也许是为了让您自己注册以添加您关心的尚未注册到 numbers.Numbers 的类型 --- 如果您想 排除 某些类型声称它们是数字,但您无法处理,这需要更加小心,因为 ABC 没有 unregister 方法 [[例如,您可以制作自己的 ABC WeirdNum 并注册有所有这些对你来说很奇怪的类型,然后首先检查 isinstance 在继续检查正常的 numbers.Number 之前 isinstance 26ec6df160e7a95fcff607b8-e6eff2e 继续成功地。

顺便说一句,如果以及何时需要检查 x 是否可以做某事或不能做某事,您通常必须尝试以下操作:

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

__add__ 的存在本身并没有告诉你任何有用的信息,因为例如所有序列都有它用于与其他序列连接的目的。例如,此检查等效于定义“数字是这样的东西,这样的东西的序列是内置函数的有效单个参数 sum ”。完全奇怪的类型(例如,当求和为 0 时引发“错误”异常的类型,例如 ZeroDivisionErrorValueError &c)将传播异常,但没关系,让用户尽快知道这种疯狂的类型在好公司中是不可接受的;-);但是,一个可以和标量相加的“向量”(Python 的标准库没有,但当然它们作为第三方扩展很受欢迎)也会在这里给出错误的结果,所以(例如)这个检查应该 _在_“不允许迭代”一个(例如,检查 iter(x) 引发 TypeError ,或者是否存在特殊方法 __iter__ -05b384在 2.5 或更早版本中,因此需要您自己检查)。

对这些复杂情况的简要了解可能足以激励您在可行的情况下转而依赖抽象基类……;-)。

原文由 Alex Martelli 发布,翻译遵循 CC BY-SA 2.5 许可协议

推荐问题