G&#252;nther Jena - 2 months ago 15x
Python Question

# Why is in python float not actually a float (at least in some cases)?

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

`==`
and
`is`
(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)`
and
`float(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 returns `True` if either argument is assigned to the same object.

In this case, they are different instances, `float(0)` and `float(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 ≥ -5 | x ≤ 256 ], which is the first example returns `True`:

``````>>> 0.0 is 0.0
True
>>> float(0) is float(0)
False
``````

In this example we can demonstrate the 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:

``````>>> 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.
False
>>> 257 is 257  # Same reference.
True
>>> 257.0 is 257.0  # Same reference. As @Martijn Pieters pointed out.
True
``````