Some objects can change value
All names that refer to the same object are affected by a mutation
Only objects of mutable types can change: lists & dictionaries
List
append(elem): Addelemto the end of the list. ReturnNone.extend(s): Add all elements of iterablesto the end of the list. ReturnNone.insert(i, elem): Insertelemat indexi. Ifiis greater than or equal to the length of the list, thenelemis inserted at the end. This does not replace any existing elements, but only adds the new elementelem. ReturnNone.remove(elem): Remove the first occurrence ofelemin list. ReturnNone. Errors ifelemis not in the list.pop(i): Remove and return the element at indexi.pop(): Remove and return the last element. ^fxmjvk.md
suits = ['coin','string','myriad']
original_suits = suits
print(suits.pop()) # 'myriad'
suits.remove('string')
print(suits) # ['coin']
suits.append('cup')
suits.extend(['sword', 'club'])
print(suits) # ['coin', 'cup','sword', 'club']
suits[2] ='spade'
suits[0:2] = ['heart', 'diamond']
print(suits) # ['heart', 'diamond','spade', 'club']
print(original_suits) # ['heart', 'diamond','spade', 'club']
"""original_suits is changed with the change of suit."""Dictionary
pop()
Mutation can happen in a function call
def mystery(s):
s.pop()
s.pop()
"""or,"""
def mystery(s):
s[2: ] = []
four = [1, 2, 3, 4]
len(four) # 4
mystery(four)
len(four) # 2I think just like c language, the argument input is the address.
mystery can take no argument.
def another_mystery():
four.pop()
four.pop()Straightly call four of global frame.
Instance of Class
Mutation
- As long as we never modify objects, a compound object is just the totality of its pieces
- A rational number is just its numerator and denominator
- This view is no longer valid in the presence of change
- A compound data object has an “identity” in addition to the pieces of which it is composed
- A list is still “the same” list even if we change its contents
- Conversely, we could have two lists that happen to have same contents, but different.
>>> a = [10]
>>> b = a
>>> a == b
True
>>> a.append(20)
>>> a == b
>>> True
>>> a
[10, 20]
>>> b
[10, 20]
>>> a is b
True>>> a = [10]
>>> b = [10]
>>> a == b
True
>>> a is b
False
>>> b.append(20)
>>> a
[10]
>>> b
[10, 20]
>>> a == b
FalseBecause in the upper one, a and b point to the same object, while in lower one, they point to different object, only have the same content in the first.
By the way, 0 == False but 0 is not False.
The Reason
Identity is different from Equality.
Identity
<exp0> is <exp1>
evaluates to True if both <exp0> and <exp1> evaluate to the same object
Equality
<exp0> == <exp1>
evaluates to True if both <exp0> and <exp1> evaluate to equal values.
Mutable Default Arguments are Dangerous
It is a part of function, not generated by a call. So when calling many times, the change of it will remain and accumulate.
def f(s=[]):
s.append(3)Every time f is called, s will be bound to the same value.
ATTENTION:
the content of mutable values can be changed in a function, since it is the address be passed in.
But, if we re-bind the name to a new list in function, would not affect, the original list. And it will do nothing, out of the function, the name is still pointing to the original list.
Let’s have an example:
def sprout_leaves(t, leaves):
if is_leaf(t):
t.extend([tree(leaf) for leaf in leaves])
else:
for branch in branches(t):
sprout_leaves(branch, leaves)
return tIt works well, since list is mutable and we changed(using extend) it in the function, so the list will be changed, even though out of function.
def sprout_leaves(t, leaves):
if is_leaf(t):
t = tree(label(t), [tree(leaf) for leaf in leaves])
else:
for branch in branches(t):
sprout_leaves(branch, leaves)
return tIt does not work, since we actually created a new list and bind the name t to the new list. As the t is just a name, out of function, t still points to the original one which is not mutated.
All in all,
Differences between Rebinding and Mutation
-
Rebinding:
self = otherorx = 5, make a local variable name point a new object. -
mutation:
self.rest = ...、list.append(),change the attribute of object and visible outside.
“Names in Python are just labels pointing to objects; reassigning a name does not mutate the object.”
So self = ... do nothing outside but self.attr = ... does!