python - 'is' operator behaves unexpectedly with floats -


i came across confusing problem when unit testing module. module casting values , want compare values.

there difference in comparison == , is (partly, i'm beware of difference)

>>> 0.0 0.0 true   # expected >>> float(0.0) 0.0 true   # expected 

as expected till now, here "problem":

>>> float(0) 0.0 false >>> float(0) float(0) false 

why? @ least last 1 confusing me. internal representation of float(0) , float(0.0) should equal. comparison == working expected.

this has how is works. checks references instead of value. returns true if either argument assigned same object.

in case, different instances; float(0) , float(0) have same value ==, distinct entities far python concerned. cpython implementation caches integers singleton objects in range -> [x | x ∈ ℤ ∧ -5 ≤ x ≤ 256 ]:

>>> 0.0 0.0 true >>> float(0) float(0)  # not same reference, unique instances. false 

in example can demonstrate integer caching principle:

>>> = 256 >>> b = 256 >>> b true >>> = 257 >>> b = 257 >>> b false 

now, if floats passed float(), float literal returned (short-circuited), in same reference used, there's no need instantiate new float existing float:

>>> 0.0 0.0 true >>> float(0.0) float(0.0) true 

this can demonstrated further using int() also:

>>> int(256.0) int(256.0)  # same reference, cached. true >>> int(257.0) int(257.0)  # different references returned, not cached. false >>> 257 257  # same reference. true >>> 257.0 257.0  # same reference. @martijn pieters pointed out. true 

however, results of is dependant on scope being executed in (beyond span of question/explanation), please refer user: @jim's fantastic explanation on code objects. python's doc includes section on behavior:

[7] due automatic garbage-collection, free lists, , dynamic nature of descriptors, may notice seemingly unusual behaviour in uses of is operator, involving comparisons between instance methods, or constants. check documentation more info.


Comments