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
b = a makes
b name refer to the same object as
a is b operation checks if both names point to the same object, so
a is b will always always be
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
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
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
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
>>> 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
sys.getsizeof(b)returns the size of object
(ctypes.c_ubyte * sys.getsizeof(b))specifies the type of byte array that
bobject can hold (
.from_address()creates an array from memory, starting at the address where the
bobject is located
arr[-4] = asets the fourth byte from the end to
32. Which has the effect of changing the constant
42(due to how
_longobjectis represented in memory (the only / digit changes) , in particular, it says that the
PYLONG_BITS_IN_DIGIT == 30, that
sys.int_infoorder of my machine, which
The code was inspired by the article: "… How to Get Rid of a Colleague Writing in Python" .