Hi,
Typically aliasing is done by assigning the 'original' variable to some other variable. But I was exploring the intricacies of aliasing, and am wondering what might explain the following phenomenon:
>>> x = 5
>>> y = 5
>>> id(x) == id(y)
True
>>> x = 'hi'
>>> y = 'hi'
>>> id(x) == id(y)
True
>>> x = [1]
>>> y = [1]
>>> id(x) == id(y)
False
Thanks
id(some_list)
always gives you the address of list object in memory,not what the list contain.
Since lists are mutable they create new object in memory every time.
>>> id([])
13622648
>>> id([])
8717336
>>> id([])
13621328
The object integer inside list container is immutable and can point to same place in memory.
>>> x = [1]
>>> y = [1]
>>> id(x) == id(y)
False
>>> # is use id()
>>> x is y
False
>>> # == dos not
>>> x == y
True
>>> # Test integer object inside of list
>>> id(x[0]) == id(y[0])
True
>>>
>>> help(id)
Help on built-in function id in module builtins:
id(obj, /)
Return the identity of an object.
This is guaranteed to be unique among simultaneously existing objects.
(CPython uses the object's memory address.)
All of these are Python peculiar properties:
Small integers are preallocated in array called
small_ints
see CPython implementation
It covers interval from -5 to 256.
So, if
x=500
and
y=500
,
id(x) == id(y)
will return
False
.
Internal behavior with string is harder to explain. Python preallocates each Python string that contains only ascii-chars and digits (may be some special chars too, i didn't explore this in deep) (see
here). So, if you try to do the same with, e.g.
abc-1
, you will end with
False
:
x = 'abc-1'
y = 'abc-1'
id(x) == id(y)
# False
This is because these strings contains
-
.
Finally, each time you are creating a list, a new object is created, even if you try to create an empty list:
x = []
y = []
id(x) == id(y)
#False
Since, -5 to 256 numbers are prealloced objects, you can do some terrible things (using ctypes which allows to get direct access to memory), e.g. let assign to object
5
different value, e.g. 8:
import ctypes
mnt = id(6) - id(5) # the number of bytes per num
ctypes.memmove(id(5), id(8), mnt) # Try to break Python's mind.... (Don't do this)
5 + 3
Output:
11