# Integer assignment (int) in Python

## Question:

Let's say you have the following code:

``````a = 32
b = a

print(a is b)
``````

How to make b become a reference to a new value in memory, and not to the value that a refers to, i.e. how to make the operation `print(a is b)` print `False` ?

`b = a` makes `b` name refer to the same object as `a` name.

The `a is b` operation checks if both names point to the same object, so `a is b` will always always be `True` after `a = b` in Python.

If you want the name `b` refer to an object other than `a` , then just assign any other object, for example, `b = None` for the example in the question, or you can delete the name `del b` altogether (if you try to use it, an exception will be thrown after that).

If you want `a` and `b` be equal ( `a == b == 32` ), but different objects ( `a is not b` ), then the answer may depend on the specific Python implementation.

For example, in CPython, small integers are cached, so `32 is (16*2) is (31+1)` … that is, there is only one object that represents `32` in CPython. Integers are immutable in Python, so arithmetic won't change whether the same object for `32` returned each time or different.

Note that you should not use the `is` operator to compare numbers. Since different objects can have the same value (be equal), for example `1000 == (999+1)` , but `1000 is not (999+1)` (in this case, `(999+1)` returns a new object different from the object, created for `1000` constants). `is` can be used to compare to a singleton — an object that only exists, such as `None` . Python does not promise that there is only one instance of objects representing numbers, so use `==` to compare integers.

There are several solutions to the literal problem ( `a == b == 32 and a is not b` ) if viewed as a puzzle (not for practical use).

To bypass the caching of small numbers, you can create an `int` derived class:

``````>>> a = 32
>>> class Int(int):
...     pass
...
>>> b = Int(a)
>>> a == b == 32 and a is not b
True
``````

Or use `float` or any other type that can be compared with integers:

``````>>> b = 32.
>>> a == b == 32 and a is not b
True
``````

Finally, if you want `type(a) == type(b) == int` , where `int` is the built-in `PyLongObject` type, then it is possible to do the evil thing and change the value of the well-known constant `42` :

``````>>> import ctypes
>>> import sys
>>> a = 32
>>> b = 42
>>> (ctypes.c_ubyte * sys.getsizeof(b)).from_address(id(b))[-4] = a
>>> a == b == 32 and a is not b
True
>>> type(a) == type(b) == int
True
>>> (32 + 10) == 32
True
``````
• `id(b)` returns the address of an object in memory representing `42` in CPython
• `sys.getsizeof(b)` returns the size of object `b` in bytes
• `(ctypes.c_ubyte * sys.getsizeof(b))` specifies the type of byte array that `b` object can hold ( `unsigned char` )
• `.from_address()` creates an array from memory, starting at the address where the `b` object is located
• `arr[-4] = a` sets the fourth byte from the end to `32` . Which has the effect of changing the constant `42` (due to how `_longobject` is represented in memory (the only / digit changes) , in particular, it says that the `python3` command uses `PYLONG_BITS_IN_DIGIT == 30` , that `sys.int_info` confirms the `sys.int_info` order of my machine, which `sys.byteorder` also confirms).

The code was inspired by the article: "… How to Get Rid of a Colleague Writing in Python" .

Scroll to Top