Python笔记,面向对象(12)内存管理机制

存储方面

1.在Python中万物接对象

  • 不存在基本数据类型
  • 0,1.2,True,False,“abc”这些全都是对象

2.所有对象中,都会在内存中开辟一块空间进行存储

  • 会根据不同的类型及其内容,开辟不同的空间大小进行存储
  • 返回该空间的地址给外界接受(称为"引用"),用于后续对这个对象的操作
    • 可通过id()函数获取内存地址(10进制)
    • 通过hex()函数可以查看对应的16进制地址
class Person:     
    pass          
                  
p = Person        
print(p)          
print(id(p))      
print(hex(id(p))) 

#结果
<class '__main__.Person'>
2495730068704
0x245151aace0
  • 3.对于整数和短小的字符,Python会进行缓存,不会创建对个相同对象
num1 = 2                   
num2 = 2                   
                           
print(id(num1), id(num2))  

#结果
1632086026576 1632086026576

4.容器对象,存储的其他对象,仅仅是其他对象的引用,并不是其他对象本身

垃圾回收方面

引用计数器

概念

  • 一个对象,会记录着自身被引用的个数
  • 每增加一个引用,这个对象的引用计数会自动+1
  • 每减少一个引用,这个对象的引用计数会自动-1

查看引用计数

  • import sys
  • sys.getrefcount: 注意会大一(调用这个函数,会被当做一个参数传递给这个函数)
import sys

class Person:
    pass



p1 = Person()

print(sys.getrefcount(p1))

p2 = p1

print(sys.getrefcount(p1))

del p2

print(sys.getrefcount(p1))

del p1


#结果
2
3
2

举例

引用计数的两个场景
  • 引用计数+1场景
    • 对象被创建:p1 = Person()
    • 对象被引用:p1 = p2
    • 对象被作为参数,传入到一个函数中
    • 对象作为一个元素,存储在容器中:i = [P1]
  • 引用计数-1场景
    • 对象的别名被显示销毁:del p1
    • 对象的别名被赋予新的对象:p1 = 123
    • 一个对象刚离开他的作用域:一个函数执行完毕时,内部的局部变量关联的对象,她的引用对象会再次被释放
    • 对象的容器被销毁,或从容器中删除对象
循环引用问题

内存泄露:一个对象在内存中无法使用,没有被释放的情况就是内存泄露

#objgraph.count()可以查看,垃圾回收器,跟踪的对象个数
import objgraph

class Person:
    pass
class Dog:
    pass

p = Person()
d = Dog()

print(objgraph.count("Person"))
print(objgraph.count("Dog"))

p.pet = d
d.master = p

#删除p,d之后,对应的对象是否被释放掉
del p
del d

print(objgraph.count("Person"))
print(objgraph.count("Dog"))

p.pet = d
d.master = p

del p
del d


#结果
1
1
1

垃圾回收

主要作用

从经历过"引用计数器机制"仍未被释放的对象中,找到"循环引用",干掉相关对象

底层机制

怎样找到“循环引用”?

在这里插入图片描述

如歌提升查找“循环引用”的性能?

在这里插入图片描述

查看以及修改机制配置参数
import gc

print(gc.get_threshold())   #查看
gc.set_threshold(200, 5, 5)   #更改


#结果
(700, 10, 10)  每查100代的,查一次1代的,依次类推

垃圾回收时机

自动回收

在这里插入图片描述

import gc

gc.disable()
print(gc.isenabled())

gc.enable()
print(gc.isenabled())

print(gc.get_threshold())
gc.set_threshold(1000, 5, 5)   #一般往大调,提升性能,垃圾回收耗时间

##
False
True
(700, 10, 10)

手动回收
import objgraph
import gc

#定义两个类
class Person:
    pass

class Dog:
    pass

#根据这两个类,创建出两个实例对象
p = Person()
d = Dog()

#让两个实例对象之间互相引用,造成循环引用
p.pet = d
d.master = p

#尝试删除可达到引用之后,测试真实对象是否有被回收
del p
del d

#通过"引用计数机制”无法回收,需要借助“垃圾回收机制”
gc.collect()  #手动触发回收,不管垃圾回收机制是否开启,括号内写几就是回收哪一代

print(objgraph.count("Person"))
print(objgraph.count("Dog"))

#
0
0
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值