Python的对象引用、可变性和垃圾回收

Python中的变量

Python中的变量和java中的是不一样的,java中的变量是一个类型指定的容器,里面存放指定类型的数据。而Python中的变量是一个指针或者说是一个便利贴用于指向某个对象。

Python中is和==的区别

is主要用于判断两个变量是不是同一个对象(指向同一个对象)

1
2
3
4
5
6
7
8
9
10
11
12
13
# b 和 a指向同一个内存地址块
In [1]: a = [1,2,3,4]

In [2]: b = a

In [3]: b is a
Out[3]: True

In [4]: id(b)
Out[4]: 4399472584

In [5]: id(a)
Out[5]: 4399472584
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 内存地址块不一样 因此是两个对象 但是存储的值是相同的 因此 == 是True
In [6]: b = [1,2,3,4]

In [7]: a = [1,2,3,4]

In [8]: b is a
Out[8]: False

In [9]: id(b)
Out[9]: 4399015176

In [10]: id(a)
Out[10]: 4398993864

In [11]: b == a
Out[11]: True

我们是不是可以认为通过赋值就是两个不同的对象呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
In [12]: a = 256 

In [13]: b = 256

In [14]: a is b
Out[14]: True

In [15]: b = 257

In [16]: b = 257

In [17]: a is b
Out[17]: False

In [18]: a = "abcd"

In [19]: b = "abcd"

In [20]: a is b
Out[20]: True

以上代码的原理是Python的内部优化机制,对于部分整型和部分短的字符串,第一次赋值时候回开辟一个内存块,再次赋值时候会指向同一个内存块,因此是同一个对象。

Python中的del语句和垃圾回收

引用计数

当给一个对象分配一个新名称或者将一个对象放入一个容器(列表、元组或字典)时,该对象的引用计数都会增加。

当使用del对对象显示销毁或者引用超出作用于或者被重新赋值时,该对象的引用计数就会减少。

可以使用sys.getrefcount()函数来获取对象的当前引用计数。多数情况下,引用计数要比我们猜测的大的 多。对于不可变数据(数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。

垃圾回收

当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。

当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们

1
2
# 获得某个类的初始化默认值
Object.__init__.defaults__
知识就是财富
如果您觉得文章对您有帮助, 欢迎请我喝杯水!