python语言特性---内存管理

python语言特性内存管理

开始于Python的函数参数传递

python在传递的时候传递都是对象的引用

对象 = (可变对象,不可变的对象)

可变对象 = (list,dict)等
不可变对象 = (string,tuple,number)等

当对象作为参数传递给函数的时候:

这块需要特别注意

1
2
3
4
5
6
7
8
9
10
11
12
13
创建一个1的对象引用,所以说a是一个引用
a = 20
def func(a):
a= 10(这个2实际上已经是一个新的对象了)
根据函数的作用域名,在函数内部的修改不可变对象的引用的时候,对本身对象外部的引用是没有影响的
但是如果外部的对象是一个可修改的对象,那么函数内部在修改这个对象引用的时候,外部对象的引用也会随之被修改
所以,在对象不可变的时候:
在内部pirnt id(a)
和在外部print id(a)
这两个是不一样的值

为什么会有这种现象呢?python是如何进行内存管理的呢?

python如何管理内存的

从机制上说分为3个部分:

1.    引用计数
2.    垃圾回收
3.    内存池机制

那什么是python的对象引用呢?引用计数又是什么?

关于引用

关于引用,个人觉的就像是一个软链接的概念,指向的内存地址是相同的

如何查看是否为同一个对象的引用可以使用id()

在Python中,每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。

我们可以使用sys包中的getrefcount(),来查看某个对象的引用计数。需要注意的是,当使用某个引用作为参数,传递给getrefcount()时,参数实际上创建了一个临时的引用。因此,getrefcount()所得到的结果,会比期望的多1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [34]: from sys import getrefcount
In [35]: a = [1, 2, 3]
In [36]: print(getrefcount(a))
2
In [37]:
In [37]: b = a
In [38]: print(getrefcount(b))
3
In [39]:

所以第一次使用getrefcount(a),得到的引用计数为2

Python的一个容器对象(container),比如表、词典等,可以包含多个对象。实际上,容器对象中包含的并不是元素对象本身,是指向各个元素对象的引用

在容器的内部调用另一个对象引用的时候,另一个对象引用计数会+1

1
2
3
4
5
6
7
8
9
In [24]: a = [1, 2, 3]
In [25]: print(getrefcount(a))
2
In [26]: b = [a, a]
In [27]: print(getrefcount(a))
4

引用减少

某个对象的引用计数可能减少。比如,可以使用del关键字删除某个引用:

1
2
3
4
5
6
7
8
9
In [2]: a = [1, 2, 3]
In [3]: b = a
In [4]: print(getrefcount(b))
3
In [5]:
In [5]: del a
In [6]: print(getrefcount(b))
2
In [7]:

如果某个引用指向对象A,当这个引用被重新定向到某个其他对象B时,对象A的引用计数减少:

1
2
3
4
5
6
7
In [19]: b = "abc"
In [20]: print(getrefcount("abc"))
13
In [21]: b = "abcd"
In [22]: print(getrefcount("abc"))
12
In [23]:

垃圾回收

当Python中的对象越来越多,它们将占据越来越大的内存,他就会启动垃圾回收(garbage collection)

比如某个新建对象,它被分配给某个引用,对象的引用计数变为1。如果引用被删除,对象的引用计数为0,那么该对象就可以被垃圾回收。比如下面的表:

1
2
a = [1, 2, 3]
del a

内存池管理

内存池管理机制,主要包括内存池以及对象缓存池