“是”运算符意外与浮游物行为 [英] 'is' operator behaves unexpectedly with floats
问题描述
与 ==
和是
(部分地,我要小心这个区别)
pre $ code >>>> 0.0是0.0
正如预期的那样#
>>> float(0.0)是0.0
真正的#如预期
正如预期的那样,是我的问题:
>>> float(0)是0.0
False
>>> float(0)是float(0)
False
为什么?至少最后一个真的让我感到困惑。 float(0)
和 float(0.0)
的内部表示应该相等。与 ==
的比较工作正常。
如何做是
的作品。它检查引用而不是值。它返回 True
,如果两个参数分配给同一个对象的话。
在这种情况下,它们是不同的实例。 float(0)
和 float(0)
具有相同的值 ==
,但就Python而言是不同的实体。 CPython实现还将整数作为单例对象缓存在此范围内 - > [x | x∈ℤ∧-5≤x≤256] :
>>> 0.0是0.0
True
>>> float(0)是float(0)#不一样的引用,唯一的实例。
False
在这个例子中,我们可以演示整数缓冲原理:
>>> a = 256
>>> b = 256
>>> a是b
True
>>> a = 257
>>> b = 257
>>> a是b
False
现在,如果将float传递给在float()
中,浮点文字被简单地返回( short-circuited ),就像在同一个引用中一样,因为不需要从现有的实例化一个新的float float:
>>> 0.0是0.0
True
>>> float(0.0)是float(0.0)
True
这可以通过使用 int()
也是:
>>> int(256.0)是int(256.0)#相同的引用,缓存。
True
>>> int(257.0)是int(257.0)#返回不同的引用,不缓存。
False
>>> 257是257#相同的参考。
True
>>> 257.0是257.0#相同的参考。正如@Martijn Pieters指出的那样。
True
然而,的结果是
也取决于它的执行范围(超出了这个问题/解释范围),请参考用户: @ 吉姆 在代码对象。甚至python的文档也包含了这个行为的一部分:
-
lockquote
由于自动垃圾收集,空闲列表以及描述符的动态性质,您可能会注意到在
的某些用途中看似不寻常的行为是
运算符,就像涉及实例方法或常量之间的比较那样。请查阅他们的文档获取更多信息。
I came across a confusing problem when unit testing a module. The module is actually casting values and I want to compare this values.
There is a difference in comparison with
==
andis
(partly, I'm beware of the difference)>>> 0.0 is 0.0 True # as expected >>> float(0.0) is 0.0 True # as expected
As expected till now, but here is my "problem":
>>> float(0) is 0.0 False >>> float(0) is float(0) False
Why? At least the last one is really confusing to me. The internal representation of
float(0)
andfloat(0.0)
should be equal. Comparison with==
is working as expected.解决方案This has to do with how
is
works. It checks for references instead of value. It returnsTrue
if either argument is assigned to the same object.In this case, they are different instances;
float(0)
andfloat(0)
have the same value==
, but are distinct entities as far as Python is concerned. CPython implementation also caches integers as singleton objects in this range -> [x | x ∈ ℤ ∧ -5 ≤ x ≤ 256 ]:>>> 0.0 is 0.0 True >>> float(0) is float(0) # Not the same reference, unique instances. False
In this example we can demonstrate the integer caching principle:
>>> a = 256 >>> b = 256 >>> a is b True >>> a = 257 >>> b = 257 >>> a is b False
Now, if floats are passed to
float()
, the float literal is simply returned (short-circuited), as in the same reference is used, as there's no need to instantiate a new float from an existing float:>>> 0.0 is 0.0 True >>> float(0.0) is float(0.0) True
This can be demonstrated further by using
int()
also:>>> int(256.0) is int(256.0) # Same reference, cached. True >>> int(257.0) is int(257.0) # Different references are returned, not cached. False >>> 257 is 257 # Same reference. True >>> 257.0 is 257.0 # Same reference. As @Martijn Pieters pointed out. True
However, the results of
is
are also dependant on the scope it is being executed in (beyond the span of this question/explanation), please refer to user: @Jim's fantastic explanation on code objects. Even python's doc includes a section on this behavior:[7] Due to automatic garbage-collection, free lists, and the dynamic nature of descriptors, you may notice seemingly unusual behaviour in certain uses of the
is
operator, like those involving comparisons between instance methods, or constants. Check their documentation for more info.这篇关于“是”运算符意外与浮游物行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!