>>> a = 3



>>> a = 3              # its an integer
>>> a = 'spam'         # now its a string
>>> a = 1.23           # now its a floating-point



>>> a = 3
>>> a = 'spam'



>>> x = 42
>>> x = 'shrubbery'     # Reclaim 42 now (unless referenced elsewhere)
>>> x = 3.1415          # Reclaim 'shrubbery' now
>>> x = [1,2,3]         # Reclaim 3.1415 now



>>> a = 3
>>> b = a



>>> a = 3
>>> b = a
>>> a = 'spam'



>>> a = 3
>>> b = a
>>> a = a + 2



>>> L1 = [2, 3, 4]
>>> L2 = L1
>>> L1 = 24



>>> L1 = [2, 3, 4]        # a mutable object
>>> L2 = L1               # make a reference to the same object
>>> L1[0] = 24            # an in-place change

>>> L1                    # L1 is different
[24, 3, 4]
>>> L2                    # but so is L2!
[24, 3, 4]



>>> L1 = [2, 3, 4]
>>> L2 = L1[:]            # make a copy of L1
>>> L1[0] = 24

>>> L1
[24, 3, 4]
>>> L2                    # L2 is not changed
[2, 3, 4]



import copy
X = copy.copy(Y)      # make a top-level "shallow" copy of any object Y
X = copy.deepcopy(Y)  # make a deep copy of any object Y: copy all nested parts



>>> x = 42
>>> x = 'shrubbery'           # Reclaim 42 now?



>>> L = [1, 2, 3]
>>> M = L                     # M and L reference the same object
>>> L == M                    # same value
True
>>> L is M                    # same object
True



>>> L = [1, 2, 3]
>>> M = [1, 2, 3]             # M and L reference different objects
>>> L == M                    # same values
True
>>> L is M                    # different objects
False



>>> X = 42
>>> Y = 42                    # should be two different objects
>>> X == Y	
True
>>> X is Y                    # same object anyhow: caching at work!
True



>>> import sys
>>> sys.getrefcount(1)        # 837 pointers to this shared piece of memory
837



A = "spam"
B = A
B = "shrubbery"



A = ["spam"]
B = A
B[0] = "shrubbery"



A = ["spam"]
B = A[:]
B[0] = "shrubbery"
