可变对象与不可变对象

在内存中创建了一个对象,这时,我们无法直接使用它,我们将这个对象赋值给一个变量,这之后,我们就可以通过这个变量来操作这个对象了,这就相当于给这个对象起一个名字一样。

变量,只是内存中对象的引用,这个变量指向了内存中的对象。所谓变量的内存地址,本质上是这个对象的内存地址。

python可变对象

python可变对象包括列表, 集合, 字典, 不可变对象包括字符串, int, float, bool, 当我们讨论可变对象与不可变对象时,实际上是在讨论这个内存里对象的值,而不是这个内存里对象的地址。

说可变,是指这个内存对象的值可以改变,说不可变,是指这个内存对象的值不可以改变。

1. 不可变对象

1.1 不可变

int, float,str, tuple都是不可变对象

a = 4
print(id(a))

程序输出结果是4297246752,现在你要这样来理解它
1、 在内存中,有一个对象,位于内存的4297246752
2、 这个对象的值是4,你无法改变它

每一次程序执行,其输出结果都会不一样,因为在内存中创建对象时,是根据可申请内存的实际情况来定的,不受任何人控制。

1.2 异议

有人会提出异议,认为可以改变,它的方法是这样的

var = 4
var = 6

这样,不就改变了这个对象的值了么?从4变成了6

1.3 真的不能变

将上面的代码稍作修改

var = 4
print(id(var))
var = 6
print(id(var))

程序输出结果是

4470806560
4470806624

注意看,两次输出的变量的内存地址是不一样的,你以为你改变了对象的值,其实,你只是创建了一个新的对象,这个对象的地址是4470806624,值是6,然后让var这个变量指向它。

而原来的那个对象,地址是4470806560,值是4,它依然存在,你没有改变它,只是现在,没有变量指向它了,系统会收回销毁这个对象,这片内存区域可以分配给其他对象使用。

1.4 验证对象的销毁

class A:
    def __del__(self):
        print("销毁对象")


a = A()
print('改变a的指向')
a = 6
print('完成对象回收')

为了验证对象的销毁,我定义一个类A,由它创建的对象是不可变对象。我重载了它的__del__方法,这个方法是在垃圾回收时调用的。根据1.3中所讲述的知识,当a重新赋值为6时,之前在内存中创建出的类A的实例由于没有变量指向它将会被回收,回收过程中,一定会调用实例的__del__方法,在两个print语句执行中间,一定会输出'销毁对象',执行上面的代码,实际输出结果和预期相符

改变a的指向
销毁对象
完成对象回收

2. 可变对象

2.1 可变

字典,集合,列表,都属于可变对象,说其可变,是指其内存中的值可变。

a = [1]
a.append(2)

print(a)

上面的代码执行时,内存中究竟是怎样变化的呢?
python可变对象
注意看,a所指向的内存地址没有发生变化,但是列表里的数据发生变化了,这就叫可变对象

2.2 赋值

lst = [1, 2]
print(id(lst))

lst = [1, 2, 3]
print(id(lst))

程序输出结果是

4358139080
4358136264

结合前面的内容来理解一下上面的代码,两次输出的内存地址是不一样的,这说明,lst = [1, 2, 3] 在内存中创建了一个新的列表对象,lst最初指向4358139080, 后来指向4358136264, 没有变量指向内存地址位于4358139080的列表,这个列表最后会被系统回收销毁。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案