Here is one consequence of the fact that we can change the contents of lists: we can change the contents of arguments to functions:
def change_list(L):
L[0] = 5
if __name__ == '__main__':
L1 = [1, 2, 3]
change_list(L1)
print(L1)
What happenned there is that the parameter L became an alias of the list L1. Therefore, when the contents of L changed, the contents of L1 changed, too.
Note that all that's going on there is that we can change the contents of lists. With both lists and integers, if we make a local variable refer to a new object, the variable which we used as an argument is unaffected:
def dont_change_list(L):
L = [5]
def dont_change_integer(n):
n = 5
if __name__ == '__main__':
L1 = [7]
dont_change_list(L1)
print(L1) #[7]
m = 7
dont_change_integer(m)
print(m) #7