Immutable object, the object pointed to The value in memory cannot be changed. When a variable is changed, since the value it refers to cannot be changed, it is equivalent to copying the original value and then changing it. This will open up a new address, and the variable will point to this new address.
# Mutable object, the value in the memory pointed to by the object can be changed. After the variable (reference to be precise) is changed, the value it refers to is actually changed directly. No copying behavior occurs, and no new outgoing address is opened. In layman's terms, it is changed in place. .
In Python, numeric types (int
and float
), string str, and tuple tuple are all immutable types . Lists, dictionaries, and sets are variable types.
It’s more intuitive to look at the code. Let’s first look at the immutable objects
First explain one pointis
is to determine whether the ids of two objects are the same, and= =
The judgment is whether the content is the same.
a = 2b = 2c = a + 0 c += 0print(id(a), id(b), id(2)) # id都相同print(c is b) #True
Look at the string
astr = 'good'bstr = 'good'cstr = astr + ''print(cstr is bstr) # Trueprint(id(astr), id(bstr), id('good')) # 三个id相同
The result is the same as the numerical type. If the following situation occurs, the variable is no longer good
astr = 'good'print(id(astr)) astr += 'aa'print(id(astr)) # id和上面的不一样
after modification. Since it is an immutable object, the value of the memory corresponding to the variable is not allowed to be changed. . When a variable is to be changed, the original value is actually copied and then changed, a new address is opened, and astr points to this new address (so the id of the previous and the previous astr is different). The value corresponding to the original astr is different because If another object points to it, it will be garbage collected. This is the same for int and float types.
Look at the tuple
add = (1, 2, 3) aee = (1, 2, 3)print(id(add), id(aee), id((1, 2, 3))) # id各不相同aee = (1, 2, 3)print(id(aee)) aee += () # 加空元组print(id(aee)) # id变了!print(aee) #(1 ,2,3)
Although it looks like they are all (1,2,3)
it should be consistent with the above. Is this a mutable object? Look again
add = (1, 2, 3) aee = add print(id(aee), id(add)) # 这两个id一样aee += (4, 5, 6)print(id(aee)) # aee的id变了!print(add) # add还是(1, 2, 3)没有变
is consistent with the numeric type and the str type. If it is a mutable object add = aee
, it is certain that they point to the same address (same id). But it is not different references to the same object, because if so, changes in aee will cause changes in add, which is not the case in tuple. So tuple is an immutable object, but it is slightly different from str and numeric types. The immutability of tuples usually means that the values stored in them cannot be changed (In some special cases, such as a list stored in a tuple, the elements in the list can be changed. But in fact, the tuple has not been changed).
For str, int, float
As long as they have the same type and the same value, then their ids will be the same. (Why do you say they have the same type?)
a = 2.0b = 2print(a is b) # False, 一个int一个float,类型都不同
2 and 2.0 are not at the same address.
lis = [1, 2, 3] lis2 = [1, 2, 3]# 虽然它们的内容一样,但是它们指向的是不同的内存地址print(lis is lis2)print(id(lis), id(lis2), id([1, 2, 3])) # 三个id都不同
Look at the assignment
alist = [1, 2, 3]# alist实际上是对对象的引用,blist = alist即引用的传递,现在两个引用都指向了同一个对象(地址)blist = alistprint(id(alist), id(blist)) # id一样# 所以其中一个变化,会影响到另外一个blist.append(4)print(alist) # 改变blist, alist也变成了[1 ,2 ,3 4]print(id(alist), id(blist)) # id一样,和上面值没有改变时候的id也一样
blist = alist
This sentence. alist
is actually a reference to the object, blist = alist
is the transfer of reference, and now both references point to the same object (address). So changes in one will affect the other.
Look at the 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)) # 相等
which is consistent with the example in the list above.
The variable object refers to a variable object that can be modified, so there is no need to make a copy and then change it. It can be changed directly in place, so no new memory will be opened, and the id remains unchanged before and after the change.
Of course this is not the case for immutable objects. You can compare it with this
abc = 3dd = abc dd = 43print(abc) # 3,并不随dd的改变而改变
But if it is a copy, it is just copying the content, and what is passed is not Not quoted. This is especially useful when you want to use the values of the list without modifying the original list.
blist = alist[:] # or alist.copy()print(alist is blist) # Falseblist.append(4)print(alist) # 还是[1,2 ,3]没有变化
As a function parameter, it is the same. Variable types pass references, while immutable types pass 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) # 改变了原来的值print(test_str) # 没有变
Of course, if you don’t want to change the value of the original list, the parameters can be passed in a copy of the column variable. alsit[:]
Looking at another interesting example, we know that list can be added to a list using +
.
a1 = [1, 2, 3] a2 = a1print(id(a1), id(a2))# 实际上是a2指向了新的对象,id已经改变。# 所以现在a2、a1并不是同一对象的两个引用了,a2变化a1不会改变a2 = a2 + [4] # 这个等式中,右边的a2还是和a1的id一样的,一旦赋值成功,a2就指向新的对象print(id(1), id(a2)) # 不等,a2的id变化了print(a1) # [1, 2, 3]没有变
If it is written like this
a1 = [1, 2, 3] a2 = a1print(id(a1), id(a2)) a2 += [4] # 相当于调用了a2.extend([4]),原地改变并没有新的对象产生print(id(1), id(a2)) # 相等,a2的id没有变化print(a1)
The difference is that a2 += [4]
, this sentence is quite Because calling a2.extend([4])
is equivalent to changing in place, and no new objects are generated.
The above is the detailed content of Detailed explanation of mutable objects and immutable objects in Python. For more information, please follow other related articles on the PHP Chinese website!