为什么'decimal.Decimal(1)'不是'numbers.Real'的实例?

14

我尝试检查变量是否是任何类型(intfloatFractionDecimal等)的数字实例。

我遇到了这个问题和它的答案:如何正确使用Python的isinstance()函数检查变量是否为数字?

然而,我想排除复数,如1j

numbers.Real类看起来很完美,但它对于Decimal数返回False...

from numbers Real
from decimal import Decimal

print(isinstance(Decimal(1), Real))
# False

相反,例如使用 Fraction(1) 就能正常工作。

文档 描述了一些应该适用于数字的操作,在一个十进制实例上测试它们没有任何错误。 Decimal 对象不能包含复数。

那么,为什么 isinstance(Decimal(1), Real) 返回 False呢?


2
https://docs.python.org/3.6/library/numbers.html#the-numeric-tower - Tom Dalton
@TomDalton 我已经阅读了,但仍然不理解。[isinstance(Decimal(1), t) for t in [Number, Complex, Real, Rational, Integral]] 返回 [True, False, False, False, False]。如果 Decimal 是一个 Number,为什么它不是其任何子类之一呢? - Delgan
1个回答

15

那么,我直接在cpython/numbers.py的源代码中找到了答案:

## Notes on Decimal
## ----------------
## Decimal has all of the methods specified by the Real abc, but it should
## not be registered as a Real because decimals do not interoperate with
## binary floats (i.e.  Decimal('3.14') + 2.71828 is undefined).  But,
## abstract reals are expected to interoperate (i.e. R1 + R2 should be
## expected to work if R1 and R2 are both Reals).

确实,将Decimal添加到float会引发TypeError错误。

我认为这违反了最小意外原则,但并不太重要。

作为一种解决方法,我使用:

import numbers
import decimal

Real = (numbers.Real, decimal.Decimal)

print(isinstance(decimal.Decimal(1), Real))
# True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接