In Python, why doesn't 'y = x; y += 1' also increment x?
Question: First create a function for displaying reference count (note that we have to
-1 each time to get the correct value, as the function itself INCREF-s the
argument)

    
    
    >>> from sys import getrefcount as rc
    >>> x=1.1
    >>> rc(x)-1
    1
    

Now make another reference to the same `PyObject`:

    
    
    >>> y=x
    
    >>> rc(x)-1
    2
    >>> rc(y)-1
    2
    
    >>> x is y
    True
    

Now perform an operation on the second handle, `y`:

    
    
    >>> y+=1
    

This should be invoking `PyNumber_InPlaceAdd` on the `PyObject` that `y`
points to.

So if this is true I would be expecting `x` to also read `2.1`

    
    
    >>> x,y
    (1.1, 2.1)
    
    >>> x is y
    False
    
    >>> rc(x)-1
    1
    >>> rc(y)-1
    1
    

So my question is, what is Python doing internally to provide the right
behaviour, rather than the behaviour I would expect from looking at
`PyNumber_InPlaceAdd`?

(Note: I am using `1.1`; if I used `1` the initial reference count would be
>300, because `1` must be used all over the place behind-the-scenes in
CPython, and it is clever enough to reuse objects.)

_(This also begs the question: if I have`foo = 20; bar = 19; bar += 1` does
this mean it has to look through all its objects and check whether there
already exists an object with this value, and if so reuse it? A simple test
shows that the answer is no. Which is good news. It would be horribly slow
once the program size gets big. So Python must just optimise for small
integers.)_


Answer: You don't need `getrefcount` for this, you can just use
[`id`](https://docs.python.org/2/library/functions.html#id):

    
    
    >>> x = 1.1
    >>> id(x)
    50107888
    >>> y = x
    >>> id(y)
    50107888 # same object
    >>> y += 1
    >>> id(y)
    40186896 # different object
    >>> id(x)
    50107888 # no change there
    

`float` objects (along with e.g. `str` and `int`) are _immutable_ in Python,
they cannot be changed in-place. The addition operation therefore _creates a
new object_ , with the new value, and assigns it to the name `y`, effectively:

    
    
    temp = y + 1
    y = temp
    

* * *

In CPython, integers from `-5` to `256` inclusive are "interned", i.e. stored
for reuse, such that any operation with the result e.g. `1` will give a
reference to _the same object_. This saves memory compared to creating new
objects for these frequently-used values each time they're needed. You're
right that it would be a pain to search all existing objects for a match every
time a new object might be needed, so this is only done over a limited range.
Using a contiguous range also means that the "search" is really just an offset
in an array.

