Why id function behaves differently with integer and float?

前端 未结 6 1286
北荒
北荒 2020-12-11 19:53

I tried the following code and It gave me different output.

>>> foo1 = 4
>>> foo2 = 2+2
>>> id(foo1)
37740064L
>>> id(foo         


        
相关标签:
6条回答
  • 2020-12-11 20:20

    For small integers and strings, that are expected to be frequently used, Python uses internal memory optimization. Since any variable in Python is a reference to memory object, Python puts such small values into the memory only once. Then, whenever the same value is assigned to any other variable, it makes that variable point to the object already kept in memory. This works for strings and integers as they are immutable and if the variable value changes, effectively it's the reference used by this variable that is changed, the object in memory with original value is not itself affected.

    That's why variables foo1 and foo2 in first case hold reference to the same integer object in memory with value 4 and therefore the ids are the same.

    First of all, floating point numbers are not 'small', and, second, the same 4.3 in memory depending on calculations might be kept as 4.3123456789 and 4.31239874654 (just example numbers to explain). So these two values are two different objects, but during calculations and displaying the meaningful part looks the same, i.e. 4.3 (in fact there's obviously many more possible values in memory for the same meaningful floating point number). So reusing the same floating point number object in memory is problematic and doesn't worth it after all.

    That's why in the second case foo1 and foo2 reference different floating point object in memory and therefore have different ids.

    See more details on how floating point numbers are kept in memory:

    http://floating-point-gui.de/

    http://docs.python.org/2/tutorial/floatingpoint.html

    Also, there's a big article on floating point numbers at Oracle docs.

    @josliber, I edited the answer before reposting as you advised.

    0 讨论(0)
  • 2020-12-11 20:23

    That is because the result of id in numeric constants is implementation defined.

    In your case, Python 2.7.2, IIRC, the issue is that the compiler builds a few useful integer constants as singletons, (from -1 to 100 or so). The rationale is that these numbers are used so frequently that it makes no sense to dynamically allocate them each time they are needed, they are simply reused.

    But that constant singleton optimization is not useful for float values, other than maybe 0.0, there are too many of them! So each time a new float value is needed it is allocated, and it gets a different id.

    For a more deeply insight, read the source! This file is from Python3, but the idea is the same: look for the small_ints array.

    0 讨论(0)
  • 2020-12-11 20:24

    Besides from the mentionned (and very true) reasons, did you verify if foo1 == foo2 at the first place? As you are dealing with floating point values, there can very easily be differences...

    0 讨论(0)
  • 2020-12-11 20:30

    id is never really predictable, not even for integers. With low the very integers 2 and 4, you just happen to hit the small integer cache. Try this:

    >>> a = 12345
    >>> b = 12345
    >>> id(a)
    33525888
    >>> id(b)
    33525852
    >>>
    
    0 讨论(0)
  • 2020-12-11 20:31

    In that case the float value containing variable may contain same data but reason behind is to mathematical rules. The only two value are consider after the point & remaining are value get neglected. so the we get two different addresses of the same data containing variables. To solve this error we can use the round() method.

    y=3.1254
    x = 3.1254
    print(round(x,2))
    print(round(y,2))
    print(id(x)==id(y))
    

    This can display the both has same addresses because in print(round(x,2)) method & print(round(y,2)) method takes the only two digits after point.

    0 讨论(0)
  • 2020-12-11 20:32

    For floating numbers, 1.0+3.3 == 4.3 is not always TRUE (in Python or other languages). and mutable objects with same value can have different IDs, too.

    0 讨论(0)
提交回复
热议问题