Python中可变对象和不可变对象

python中对象可分为:可变对象和不可变对象
先从数据类型角度理解可变对象和不可变对象。

抽象数据类型的操作一般分为三类:

1
2
3
4
5
6
7
8
1、构造操作: 这类操作主要是基于一些已知信息,产生这个类的实例对象。类似银行进行开通账户
2、解析操作:这类操作是获取对象的一些有用信息,其结果反应了对象的一些特征,但返回的不是对象本身。类似银行查询账户余额
3、变化操作 :这类操作是修改对象内部的信息和状态。比如一个银行账户进行转账操作
如果一个类型,具只具有1和2两种操作,也就说只具有构造和解析操作,那么这个类型就是不可变类型,这个类型的对象就是不可变对象
如果一个类型,具有1、2、3三种操作,这个类型就是可变类型,这个类型的对象就是可变对象。

可变对象:对象所指向的内存中的值不能被改变,当改变这个变量的时候,原来指向的内存中的值不变,变量不再指向原来的值,而是开辟一块新的内存,变量指向新的内存。
举个例子:

1
2
3
4
5
6
7
8
9
10
11
>>> a=5
>>> print id(a)
140433054259208
>>> a= 4
>>> print id(a)
140433054259232
>>> print id(a),id(4)
140433054259232 140433054259232
>>> print id(a),id(5)
140433054259232 140433054259208
>>>

打印的结果表明:不可变对象int的变量a改变后,未改变之前指向内存中5,改变后开辟一块新内存指向4
由于是不可变对象,变量对应内存的值不允许被改变。当变量要改变时,实际上是把原来的值复制一份后再改变,开辟一个新的地址,astr再指向这个新的地址(所以前后astr的id不一样),原来astr对应的值因为不再有对象指向它,就会被垃圾回收。

再来看一下字符串str

1
2
3
4
5
6
7
8
>>> a='hello'
>>> print id(a)
4385118896
>>> a =a +' world'
>>> print a
hello world
>>> print id(a)
4385119040

结果是一样的,也是开辟新内存,指向新内存中的值

不可变对象:对象指向的内存中的值会改变,当更改这个变量的时候,还是指向原来内存中的值,并且在原来的内存值进行原地修改,并没有开辟新的内存。

1
2
3
4
5
6
7
8
>>> list=[1,2,3,4]
>>> print id(list)
4384947808
>>> list[2]=5
>>> print list
[1, 2, 5, 4]
>>> print id(list)
4384947808

结果表明: 列表list在改变前后id并未发生改变,可变对象由于所指对象可以被修改,所以无需复制一份之后再改变,直接原地改变,所以不会开辟新的内存,改变前后id不变。

在Python中,数值类型int 、float、 字符串str 、元祖tuple、boole 都是不可变对象
列表list、集合set、字典dict都是可变对象

-