Python with 工作原理、装饰器、回收机制、内存管理机制、拷贝、作用域等(12)


博客地址推荐:
缓存了整数和短字符串 , 因此每个对象在内存中只存有一份 , 引用所指对象就是相同的 , 即使使用赋值语句 , 也只是创造新的引用 , 而不是对象本身;
没有缓存长字符串、列表及其他对象 , 可以由多个相同的对象 , 可以使用赋值语句创建出新的对象 。
在中 , 每个对象都有指向该对象的引用总数:引用计数
查看对象的引用计数:sys.getrefcount()
当使用某个引用作为参数 , 传递给()时 , 参数实际上创建了一个临时的引用 。因此 , ()所得到的结果 , 会比期望的多1 。
的一个容器对象(比如:表、词典等) , 可以包含多个对象 。
由上可见 , 实际上 , 容器对象中包含的并不是元素对象本身 , 是指向各个元素对象的引用 。
引用计数减少包含哪些方面:
1、对象的别名被显式的销毁
import systemp1 = "wrist_waking"temp2 = temp1print(sys.getrefcount("wrist_waking")) # 5del temp2print(sys.getrefcount("wrist_waking")) # 4
2、对象的一个别名被赋值给其他对象
import systemp1 = "wrist_waking"temp2 = temp1print(sys.getrefcount("wrist_waking")) # 5temp2 = "唤醒手腕"print(sys.getrefcount("wrist_waking")) # 4
3、对象从一个容器对象中移除 , 或容器对象本身被销毁
temp = "wrist_waking"list = [1, 2, temp]print(sys.getrefcount("wrist_waking"))list.remove(temp)# del listprint(sys.getrefcount("wrist_waking"))
4、一个本地引用离开了它的作用域 , 比如上面的foo(x)函数结束时 , x指向的对象引用减1
import sysdef foo():var = "wrist_waking"print("函数执行时候:", sys.getrefcount("wrist_waking")) # 5temp = "wrist_waking"print("函数执行之前:", sys.getrefcount("wrist_waking")) # 6foo()print("函数执行之后:", sys.getrefcount("wrist_waking")) # 5
当中的对象越来越多 , 占据越来越大的内存 , 启动垃圾回收( ) , 将没用的对象清除 。
当的某个对象的引用计数降为0时 , 说明没有任何引用指向该对象 , 该对象就成为要被回收的垃圾 。比如某个新建对象 , 被分配给某个引用 , 对象的引用计数变为1 。如果引用被删除 , 对象的引用计数为0 , 那么该对象就可以被垃圾回收 。
del temp后 , 已经没有任何引用指向之前建立的 [1, 2, 3]  , 该表引用计数变为0 , 用户不可能通过任何方式接触或者动用这个对象 , 当垃圾回收启动时 , 扫描到这个引用计数为0的对象 , 就将它所占据的内存清空 。
垃圾回收注意事项:
1、垃圾回收时 , 不能进行其它的任务 , 频繁的垃圾回收将大大降低的工作效率;
2、只会在特定条件下 , 自动启动垃圾回收(垃圾对象少就没必要回收)
3、当运行时 , 会记录其中分配对象( )和取消分配对象( )的次数 。当两者的差值高于某个阈值时 , 垃圾回收才会启动 。
问题产生:基于引用计数的回收机制 , 每次回收内存 , 都需要把所有对象的引用计数都遍历一遍 , 这是非常消耗时间的 , 于是引入了分代回收来提高回收效率 , 分代回收采用的是用“空间换时间”的策略 。