当我比较具有相同值的int和float对象时,为什么python返回True?

例如:

1

2>>> 5*2 == 5.0*2.0

>>> True

回答题目:实际上从来没有。这与类型转换无关,但与比较逻辑有关。

你可以在cpython比较int和float中找到这个答案。虽然不能保证,但如果其他实现类似,我也不会感到惊讶。

Objects of different types, except different numeric types, never compare equal.

还有:

Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the"narrower" type is widened to that of the other, where integer is narrower than floating point, which is narrower than complex. Comparisons between numbers of mixed type use the same rule.

https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex

比较逻辑由每种类型的__eq__方法实现。标准的数字类型是以一种支持相互比较(和算术运算)的方式实现的。作为一种语言,python从不进行隐式类型转换(就像javascript的==操作符会进行隐式类型转换)。

如python文档所述,==不是二进制算术运算符。根据链接到的页面,这是一个比较操作。

是的,但"混合类型的数字之间的比较使用相同的规则。"不过,我在顶部添加了一个更恰当的引号。

您可以查看cpython实现的源代码。

函数前面是解释如何尝试转换的注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14/* Comparison is pretty much a nightmare. When comparing float to float,
* we do it as straightforwardly (and long-windedly) as conceivable, so
* that, e.g., Python x == y delivers the same result as the platform
* C x == y when x and/or y is a NaN.
* When mixing float with an integer type, there's no good *uniform* approach.
* Converting the double to an integer obviously doesn't work, since we
* may lose info from fractional bits. Converting the integer to a double
* also has two failure modes: (1) an int may trigger overflow (too
* large to fit in the dynamic range of a C double); (2) even a C long may have
* more bits than fit in a C double (e.g., on a 64-bit box long may have
* 63 bits of precision, but a C double probably has only 53), and then
* we can falsely claim equality when low-order integer bits are lost by
* coercion to double. So this part is painful too.
*/

其他实现不能保证遵循相同的逻辑。

这个评论更像是关于具体的实现细节,以及获取所需行为所需的噩梦。这并不能解释为什么行为首先是需要的。

简单的答案是语言是这样设计的。以下是支持这一点的文档的摘录:

6.10.1价值比较

Numbers of built-in numeric types (Numeric Types — int, float, complex) and of the standard library types fractions.Fraction and decimal.Decimal can be compared within and across their types, with the restriction that complex numbers do not support order comparison.

换句话说,我们希望具有相同值的不同数字类型相等。

PEP 20

Special cases aren't special enough to break the rules.

Although practicality beats purity.

除了在最常见的情况下使生活变得困难之外,使数字类型不具有可比性还有什么好处?

10 == 10.0转换为对(10).__eq__(10.0)的调用(或者更正式地说,int.__eq__(10, 10.0))。int.__eq__的实现可以处理与其他类型的比较,但是在语言级别没有类型转换。

我想,下一个问题是,"int.__eq__的实现"是否需要类型转换?同意在Python级别没有转换,但我不确定在任何地方都没有转换。

根据定义,这是一个实现细节。例如,cpython、pypy和jython可能都会做不同的事情。但该语言并未规定将int.__eq__(10, 10.0)转换为float.__eq__(10.0, 10.0)。

既然是这样,我们也不想有半真半假的事实,我必须好好地告诉你:a == b并不等同于a.__eq__(b)。比较机制比这要复杂得多。例如,如果a不支持与b的比较,则使用b.__eq__(a)。更多详细信息。

@切普纳,如果是这样的话,也许他们都做了某种类型转换。当然,我对单个实现的了解还不足以提出这样的要求。但如果这是真的,知道这一点仍然很有用。

@在语言层面上,他们是对等的。在确定是否需要呼叫b.__eq__(a)之前,您仍然需要运行a.__eq__(b)。从词汇上讲,翻译是合理的。从语义上讲,这取决于实现。(我可以想象一个实现,其中int.__eq__比较两个值本身,我也可以想象一个实现,其中int.__eq__引发异常,并将比较委托给float.__eq__。)

@JPPpython不进行类型转换。任何特定的python实现都可能。

@切普纳,这在我之前的评论中显然是明确的。进一步深入研究,例如,cpython实现,可能对OP很有用。

如果OP在这个问题中提到了一个具体的实现,我会解决这个问题,但他没有(是的,大多数初学者可能不会区分语言和cpython;这并不意味着我不能。)

从文档中:

Python fully supports mixed arithmetic: when a binary arithmetic
operator has operands of different numeric types, the operand with the
"narrower" type is widened to that of the other, where plain integer
is narrower than long integer is narrower than floating point is
narrower than complex. Comparisons between numbers of mixed type use
the same rule.

根据这个5*2扩大到10.0,等于10.0如果您正在比较混合数据类型,那么结果将在具有长范围的数据类型的基础上考虑,因此在您的情况下,浮点范围大于int最大浮点数可以是1.7976931348623157E+308整数最大值可以是-->9223372036854775807

谢谢

如python文档所述,==不是二进制算术运算符。在本页中,它是一个比较操作。

你好,埃里克,谢谢你的更正,但它也将遵循与比较运算符相同的规则。假设二元运算符4.0/2给出2.0,比较运算符4.0==4给出真值,但这里唯一的区别是,4.0/2的o/p被转换为float,但在4.0==4中,在o/p处看不到(当得到布尔结果时),但在内部,它也是这样做的。

另一个答案指向源代码,它向我们展示了简单地将一种类型转换为另一种类型的方法,但不满足特定的比较要求。将浮点转换为更宽的整数无法工作,因为3.25 == 3将错误地返回true,因为转换将丢弃.25。由于精度降低,将整数转换为浮点值失败。您断言python通过执行您所说的"加宽"来实际实现==的基础是什么(例如文档)?

正如其他答案所解释的那样,文档中的"混合类型数的比较使用相同的规则"。这一行很不幸,也有误导性。有一个(非常)长期存在的问题有待解决:bugs.python.org/issue12067

嗨,埃里克,谢谢你的纠正。

==运算符只比较值,而不比较类型。您可以使用"is"关键字实现与在其他语言中使用==相同的效果。例如

15 is 5.0

退货假

is不等于===!埃多克斯1〔17〕

1==

是比较运算符

你实际上是在问解释器你的表达方式的两边是否相等。

换句话说,您要求它返回一个布尔值,而不是转换数据类型。如果要转换数据类型,则必须在代码中隐式转换。

为什么投反对票?根据python文档,"数字……可以在它们的类型内或跨类型进行比较……它们在数学上(算法上)进行比较……"因此,根据数学定义,==是两边相等的。该文档没有说明类型已转换。它以数学比较的方式指定行为。

我没有投反对票,但你回答了(正确的)正文中的问题,而忽略了标题。