Mutable objects and immutable objects in Python
What is a mutable/immutable object
An immutable object in which the object points to an in-memory value that cannot be changed. when a variable is changed, because the value it refers to cannot be changed, it is equivalent to copy the original value and then change, this will open a new address, the variable point to the new address.
A mutable object in which the object points to an in-memory value that can be changed. variables (accurately referred to) after the change, is actually the value of its direct change, and did not occur replication behavior, nor open up new addresses, popular point is to change in situ .
In Python, numeric types ( int
and float
), strings str, tuple tuples are immutable types. The list, dictionary dict, and set set are mutable types.
Or see the code more intuitive. See Non-mutable objects first
Examples of immutable objects
The first point is
is to determine whether the IDs of two objects are the same, and ==
whether the content is the same.
A = 2b = 2c = A + 0 c + = 0print (ID (a), id (b), ID (2)) # The IDs are all the same print (c is b) #True
Look again at the string
Astr = ' good ' BSTR = ' good ' CStr = Astr + ' Print (CStr is BSTR) # Trueprint (ID (ASTR), ID (BSTR), ID (' good ')) # three ID same
Is the same as the result of a numeric type. If this is the case, the variable is not modified after thegood
Astr = ' good ' Print (ID (astr)) astr + = ' AA ' Print (ID (ASTR)) # ID is not the same as above
because it is an immutable object, the value of the variable corresponding to the memory is not allowed to be changed. When the variable to change, in fact, the original value is copied a copy and then change, open a new address, astr again point to the new address (so the ID of the front and back astr is not the same), the original astr corresponding value because no longer have the object point to it, it will be garbage collection. This is the same for int and float types.
Look at the tuple again.
Add = (1, 2, 3) Aee = (1, 2, 3) print (ID (add), ID (AEE), id ((1, 2, 3)) # ids are different AEE = (1, 2, 3) print (ID (AEE)) Aee + = () # Add empty tuple print (ID (AEE)) # ID changed! Print (AEE) # (1, 2, 3)
Although it all seems (1 ,2, 3)
to be supposed to be consistent with the above. Is this a mutable object? Look again
Add = (1, 2, 3) AEE = add print (ID (AEE), id (add)) # These two IDs are the same AEE + = (4, 5, 6) Print (ID (AEE)) # AEE ID changed! Print (add) # Add or (1, 2, 3) does not change
And the value type is the same as the STR type. If it is a mutable object add = aee
, they point to the same address (the same ID) is positive. But not a different reference to the same object, because if so, the change of AEE will cause the change of add, which is not the case in the tuple. So a tuple is an immutable object, but a little bit different from STR and numeric types. The commonly said tuple can not be changed many times refers to the stored value can not be changed ( some special cases, such as a tuple inside the list, can change the elements in the list.) But in fact the tuple has not been changed ).
For str、int、float
as long as they are of the same type, the values are the same, and their IDs are the same. (Why would you say the same type?) )
A = 2.0b = 2print (A is B) # False, an int is a float and the types are different
2 and 2.0 are not on one address.
Examples of mutable objects
Lis = [1, 2, 3]lis2 = [1, 2, 3]# although their contents are the same, but they point to different memory addresses print (LIS is Lis2) print (ID (LIS), ID (LIS2), id ([1, 2, 3]) # Three IDs are different
And then look at the assignment.
Alist = [1, 2, 3]# alist is actually a reference to an object, blist = Alist is a reference pass, and now two references point to the same object (address) blist = Alistprint (ID (alist), ID (blist)) # ID # So one of the changes will affect another blist.append (4) print (alist) # change blist, Alist also becomes [1, 2, 3 4]print (ID (alist), ID (blist)) # ID is the same as the ID when the face value has not changed
blist = alist
This sentence. alist
is actually a reference to the object, blist = alist
which is the passing of the reference, and now two references point to the same object (address). So one of the changes will affect the other one.
And look at set.
ABB = {1, 2, 3}ACC = Abbprint (ID (ABB), ID (ACC)) Acc.add (4) print (ABB) # {1, 2, 3, 4} print (ID (ABB), ID (ACC)) # Equal
It is consistent with the example above list.
Mutable objects because the object can be modified, so there is no need to duplicate a copy and then change, directly in situ changes, so will not open up new memory, change the ID and the same.
Of course the immutable object is not like this, can compare with this
ABC = 3DD = ABCDD = 43print (ABC) # 3, does not change with DD
But if it is a copy, it is simply copying the contents of the past, passing it and not referencing it. This is especially useful when you want to use the values of the list and don't want to modify the original list.
Blist = alist[:] # or alist.copy () print (Alist is blist) # falseblist.append (4) print (alist) # or [3] no change
As a function parameter
As a function parameter, it is the same, the mutable type passes a reference, and the immutable type passes the content.
Test_list = [1, 2, 3, 4]test_str = ' HAHA ' def Change (alist): alist.append (5) def not_change (astr): astr.lower () Change (test_list) not_change (test_str) print (test_list) # changed the original value print (TEST_STR) # did not change
Of course, if you don't want to change the value of the original list, the parameter can pass in the column's copy.alsit[:]
An interesting example
Looking at an interesting example, we know that list can be used to +
add a listing.
a1 = [1, 2, 3]A2 = A1print (ID (A1), ID (A2)) # is actually A2 pointing to the new object, the ID has changed. # so now A2, A1 is not the same object of two references, A2 change A1 will not change a2 = a2 + [4] # in this equation, the right of the A2 is the same as the A1 ID, once the assignment succeeds, A2 points to the new object print (ID (1), ID (A2)) # Range , A2 's ID has changed print (A1) # [1, 2, 3] has not changed
If this is the case
a1 = [1, 2, 3]A2 = A1print (ID (A1), ID (A2)) a2 + = [4] # is equivalent to calling A2.extend ([4]), where there is no new object producing print (ID (1), ID (A2)) # Equal, A2 ID not changed print (A1)
The difference is that a2 += [4]
this is equivalent to invoking a a2.extend([4])
change in place, and no new object is generated.