内存管理对于编写出高效率的Windows程序是非常重要的,这是因为Windows是多任务系统,它的内存管理和单任务的DOS相比有很大的差异。那么python如何进行内存管理呢?一起来了解下吧:
python如何进行内存管理
一、对象的引用计数机制
python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数
引用计数增加的情况:
1. 一个对象分配一个新名称
2. 将其放入一个容器中
引用计数减少的情况:
1. 使用del语句对对象别名显示的销毁
2. 引用超出作用域或被重新赋值
sys.getrefcount()函数可以获得对象的当前引用计数
多数情况下,引用计数比你猜测的要大得多。对于不可变数据(如数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。
二、垃圾回收
当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
当两个对象a 和b 相互引用时,del语句可以减少a和b的引用次数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄漏)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。
三、内存池机制
python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
1. Pymalloc机制。为了加速python的执行效率,python引入了一个内存池机制,用于管理对小块内存的申请和释放。
2. python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。
3. 对于python对象,如整数,浮点数和list,都有其独立的私有内存池,对象间不共享它们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
python怎么内存管理
内存管理
包括:
变量无须事先声明
变量无须指定类型
不用关心内存管理
变量名会被"回收"
del 语句能够直接释放资源
变量定义
python中, 变量在*次被赋值时自动声明, 和其它语言一样, 变量只有被创建和赋值后才能被使用
动态类型
变量名无须事先声明, 也无须类型声明
对象的类型和内存占用都是运行时确定的
内存分配
python解释器会自动进行内存管理, 不用开发人员去关心
引用计数
要保持追踪内存中的状态, python使用了引用计数, 就是python内部记录着所有使用中的对象各有多少引用.
一个内部跟踪变量, 称为一个引用计数器, 至于每个对象各有多少引用, 简称引用计数, 当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0时, 它被垃圾回收
增加引用计数
当对象被创建赋值给变量时, 该对象的引用计数就被设置为1
当同一个对象又被赋值给其他变量时, 或作为参数传递给函数, 方法或类实例时, 或者被赋值为一个窗口对象的成员时, 该对象的一个新的引用, 或者作为别名, 就被创建.
减少引用计数
当对象的引用被销毁时, 引用计数会减少, 明显的例子就是当引用离开其作用范围时, 这种情况最经常出现在函数运行结束时, 所有局部变量都被自动销毁, 对象的引用计数也就减少
垃圾收集
不再被使用的内存会被一种称为垃圾收集的机制释放
注: 解释器跟踪对象的引用计数, 垃圾回收机制负责释放内存, 垃圾收集器是一块独立代码, 它用来寻找引用计数为0的对象, 它也负责检查虽然引用计数大于0但是也应该被销毁的对象
引用语义: python中在变量里保存值(对象)的引用, 采用这种方式, 变量所需的存储空间大小一致, 因为其只需要保存一个引用
值语义变量的值直接保存在变量的存储区里, 这样一个整数类型的变量就需要保存一个整数所需的空间, 一个浮点数变量就需要足够的空间存储一个浮点数. C中就是值语义
python的内存管理机制
先从较浅的层面来说,Python的内存管理机制可以从三个方面来讲
(1)垃圾回收
(2)引用计数
(3)内存池机制
一、垃圾回收:
python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值。对Python语言来讲,对象的类型和内存都是在运行时确定的。这也是为什么我们称Python语言为动态类型的原因(这里我们把动态类型可以简单的归结为对变量内存地址的分配是在运行时自动判断变量类型并对变量进行赋值)。
二、引用计数:
Python采用了类似Windows内核对象一样的方式来对内存进行管理。每一个对象,都维护这一个对指向该对对象的引用的计数。如图所示(图片来自Python核心编程)
、
x = 3.14
y = x
我们首先创建了一个对象3.14, 然后将这个浮点数对象的引用赋值给x,因为x是*个引用,因此,这个浮点数对象的引用计数为1. 语句y = x创建了一个指向同一个对象的引用别名y,我们发现,并没有为Y创建一个新的对象,而是将Y也指向了x指向的浮点数对象,使其引用计数为2.
python内存管理的方法
1)动态类型
1.1)核心思想
python中"一切皆对象".作为"动态语言",python遵循"对象与引用分离"的核心思想.
1.2)一切皆对象
常见的变量,如整数、字符串、列表等,在python中一切皆为对象
a = 1
整数1为一个对象,是储存在内存中的实体.
对象名a为一个引用,我们不能直接接触到"对象实体",只能通过引用指向去访问,引用可以随时指向一个新的对象.
1.3)赋值操作:可变对象、不可变对象
不可变数据对象:不能改变对象本身,只能改变引用的指向;如整形、字符串、元祖等
a = 5
b = a
a = a + 2
解析:此时a = 7,b = 5.验证了不可变对象只能改变引用的指向,各个引用相互独立,互不影响.
可变数据对象:引用其元素(类似于L[0]),改变对象的本身;如列表,字典等
L1 = [1,2,3]
L2 = L1
L1[0] = 100
解析:此时L1 = L2 = [100,2,3].验证了可变对象可以通过引用其元素,改变对象本身
1.4)从动态类型看函数的参数传递
def f(x):
x = 100
print x
a = 1
f(a)
print a
解析:参数x是一个新的引用,指向a所指的对象.此处为不可变对象,引用a和x之间是相互独立的.参数x的操作不会影响引用a.
def f(x):
x[0] = 100
print x
a = [1,2,3]
f(a)
print a
解析:参照上一个例子,此处为可变对象传参,可以通过引用其元素改变对象本身.所以此处a和x都为[100,2,3]
1.5)垃圾回收
python采取了一种简单的垃圾回收机制:即引用计数(from sys import getrefcount()).垃圾回收时,python不能进行其他任务,频繁的垃圾回收会大大降低python的工作效率.因此,python会在特定的情况下,自动启动垃圾回收机制.
通过gc模块查看垃圾回收阀值.
import gc
print gc.get_threshold()
输出(700,10,10)
解析:700是垃圾回收的阀值:内存中分配对象的次数-取消分配对象的次数=700;可以通过set.threshold()设置.
手动启动垃圾回收机制:gc.collect()
1.6)分代回收
存活越久的对象,处于信任和效率,越不可能在后面的程序中变为垃圾,所以减少垃圾回收扫描他们的频率.
python将所有的对象分为0,1,2三代.所有新建的对象都是0带对象.当经过某一次垃圾回收,依然存活,那么它就被归入下一代对象.
参考1.5,输出中包含2个10,分别代表:每10次0代对象垃圾回收,会进行1次1代对象垃圾回收;每10次1代对象垃圾回收,会进行1次2代对象垃圾回收
我们在平时应该避免对2代对象频繁扫描:gc.set_threshold(700,10,20)