As your question evolved, different iterations of it require different answers:
None
None
is a singleton, so all references to it refer to the same object and have the same address. This means that, for a given Python process, id(None)
always returns the same value. It also means that we can test for None
using the is
operator:
<expression> is None
Strings
Strings are subject to interning, where the interpreter folds identical string literals to conserve storage. More on this in Python string interning.
The way this happens to be implemented means that your string example breaks if we replace one of the literals with an expression involving a variable:
>>> aami='Aami'
>>> g=[[aami+'r']*3]*3
>>> f=[['Aamir','Aamir','Aamir']]*3
>>> id(g)==id(f)
False
>>> id(g[0][0])==id(f[0][0])
False
Integers
Interestingly, CPython also chooses to intern small integers:
>>> x=1
>>> y=1
>>> x is y
True
>>> x=100000
>>> y=100000
>>> x is y
False
More on this in "is" operator behaves unexpectedly with integers.
Concretely, this means that your first example breaks if we try it with much larger integers:
>>> g=[[100000]*3]*3
>>> f=[[100000,100000,100000]]*3
>>> id(g)==id(f)
False
>>> id(g[0][0])==id(f[0][0])
False