[python]python的可变对象和不可变对象
说明
在python中处处皆对象,那么具体细分又可以分为可变类型和不可变类型对象,今天来详细讨论一下。
is 和 == 的区别
先提前说一下is和==的区别以帮助理解。
is是判断两者是否属于同一内存,即id(a) == id(b).而等于则是通过比较两个值的大小是否相同。以下是例子:
a = 'hello world'
b = 'hello world'
a == b #返回True
a is b #返回False
可变对象和不可变对象
由于python中万物皆对象,而且对于调用不存在值调用这一说法,所有的调用的都是对象的引用,那么根据其引用的对象是否能够修改可以分为可变对象和不可变对象。
其中可变对象为:list, set, dict
不可变对象为:int,string,float,tuple
不可变对象
由于Python中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的。所以当对不可变对象重新赋值的时候,会重新开辟一段内存空间,并将地址引用指向新开辟的空间,原有的内存空间将被回收。以下是一个例子:
print(id(100)) # 140726575113072
a = 100
print(id(a)) # 140726575113072
b = 100
print(id(b)) # 140726575113072
a += 2
print(id(a)) # 140726575113136
b = 102
print(id(b)) # 140726575113136
a和b为相同值时,其对应的内存空间是一致的;当a值发生变化时,不是在原有内存上进行修改,而是重新开辟了内存空间进行修改,然后指向新的地址。但是需要注意的是,由于小数缓存机制,[-5,257]之间的整数使用的共用的缓存的空间,当超过257时,即使相同的数值也会分配不同的地址空间。
可变对象
可变对象的引用指向了存储空间的首地址,而且有关于list的meta信息和object是分开的,因此在list中可以存储不同的数据类型,当添加新元素时,会在meta中增加相应的地址,实际上list名称是地址引用的引用,因此在改变list内容后,其指向的地址并不会发生改变。以下是一个例子:
l = [1,2,3,4]
l2 = [1,2,3,4]
print(l is l2) # id(l) == id(l2) false
id1 = id(l)
l.append(5)
id2 = id(l)
print(id1 == id2) # true
list在发生变化后其指向的内存空间并没有发生改变。