Python Forum

Full Version: Intricacies of Aliasing
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
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