1.垃圾回收GC(内存管理)——JAVA核心思想
引用计数机制;GC机制;不要手动管理,会引起巨大的性能问题;
当Python中的对象越来越多,占据越来越大的内存,启动垃圾回收(garbage collection),将没用的对象清除。
(将最不容易变化的对象(引用计数大的对象)往一个方向移动就是JAVA的内存管理机制,没用的对象删除)
1、原理
当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾。
比如某个新建对象,被分配给某个引用,对象的引用计数变为1。
如果引用被删除,对象的引用计数为0,那么该对象就可以被垃圾回收。
引用计数增加:
赋值给其他变量就增加引用计数,例如x=3;y=x
引用计数减少:
1.函数运行结束时,局部变量就会自动销毁,引用计数减少;
2.变量被赋值给其他对象。eg: x=3,y=x,x=4;
2、解析del
del 可以使 对象的引用计数减 1,该表引用计数变为0,用户不可能通过任何方式接触或者动用这个对象,当垃圾回收启动时,Python扫描到这个引用计数为0的对象,就将它所占据的内存清空。
注意
- 1、垃圾回收时,Python不能进行其它的任务,频繁的垃圾回收将大大降低Python的工作效率;
- 2、Python只会在特定条件下,自动启动垃圾回收(垃圾对象少就没必要回收)
- 3、当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。
当两者的差值高于某个阈值时,垃圾回收才会启动。
>>> import gc
>>>
>>> gc.get_threshold() #gc模块中查看垃圾回收阈值的方法
(700, 10, 10)
>>>
阈值分析:
700 即是垃圾回收启动的阈值;
每10 次 0代 垃圾回收,会配合 1次 1代 的垃圾回收;而每10次1代的垃圾回收,才会有1次的2代垃圾回收;
当然也是可以手动启动垃圾回收:
>>> gc.collect() #手动启动垃圾回收
52
>>> gc.set_threshold(666, 8, 9) # gc模块中设置垃圾回收阈值的方法
>>>
何为分代回收(JAVA核心思想)
内存碎片化:数据排列在内存中形成大量空洞;
引用计数机制:
- Python将所有的对象分为0,1,2三代;
- 所有的新建对象都是0代对象;
- 当某一代对象经历过垃圾回收,依然存活,就被归入下一代对象。
分代技术是一种典型的以空间换时间的技术,这也正是java里的关键技术。这种思想简单点说就是:对象存在时间越长,越可能不是垃圾,应该越少去收集。
这样的思想,可以减少标记-清除机制所带来的额外操作。分代就是将回收对象分成数个代,每个代就是一个链表(集合),代进行标记-清除的时间与代内对象存活时间成正比例关系。
从上面代码可以看出python里一共有三代,每个代的threshold值表示该代最多容纳对象的个数。默认情况下,当0代超过700,或1,2代超过10,垃圾回收机制将触发。
0代触发将清理所有三代,1代触发会清理1,2代,2代触发后只会清理自己。
标记-清除机制,顾名思义,首先标记对象(垃圾检测),然后清除垃圾(垃圾回收)。
首先初始所有对象标记为白色,并确定根节点对象(这些对象是不会被删除),标记它们为黑色(表示对象有效)。
将有效对象引用的对象标记为灰色(表示对象可达,但它们所引用的对象还没检查),检查完灰色对象引用的对象后,将灰色标记为黑色。
重复直到不存在灰色节点为止。最后白色结点都是需要清除的对象。
如何解决循环引用可能导致的内存泄露问题呢?
2.程序控制结构——顺序、分支、循环
这一节的重点是
1.练逻辑(严格的逻辑),练数据判断:
2.边界问题要注意;
前包后不包:range()、
前后都包:3.数据验证是后面要做的事情;
自定义对象的“布尔真假”
我们常说,在 Python 里,“万物皆对象”。其实,不光“万物皆对象”,我们还可以利用很多魔法方法(文档中称为:user-defined method),来自定义对象的各种行为。我们可以用很多在别的语言里面无法做到、有些魔法的方式来影响代码的执行。 比如,Python 的所有对象都有自己的“布尔真假”:
布尔值为假的对象:None, 0, False, [], (), {}, set(), frozenset(), … …
布尔值为真的对象:非 0 的数值、True,非空的序列、元组,普通的用户类实例,… …
通过内建函数 bool(),你可以很方便的查看某个对象的布尔真假。而 Python 进行条件分支判断时用到的也是这个值:
#bool函数查看真假;
>>> bool(object())
True
网友评论