python内存管理

对象存储:
1:python中万物皆对象
2:所有的对象都会在内存中开辟一块空间进行存储,返回这个内存空间的地址给外界操作(引用,指针)可以通过id()查看内存地址10进制,hex()转换成16进制
3:对于整数和短小的字符,python会进行缓存,创建的对象时指向的是同一个。
4:容器对象存储其他对象时,存储的是对象的引用(地址),并不是对象本身。

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: json_steve


class Test1(object):
    pass

t = Test1()
print(t)
print(id(t))
print(hex(id(t))

结果

# <__main__.Test1 object at 0x010D7950>
# 17660240
# 0x10d7950

引用计数机制:
1:引用计数器:一个对象会记录自身被引用的个数,每增加一个引用这个对象的引用计数就会加1,每减少一个引用,这个对象的引用计数就会减一。当引用计数是0是,系统会把这个对象当成垃圾回收,自动释放。可以用 sys.getrefcount(对象)查看引用计数,注意此时这个方法无论调用多少次也会增加一个引用计数。如果没有人引用是测试不出来的。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: json_steve

import sys


class Test1(object):
    pass

t = Test1()
print(sys.getrefcount(t))
t1 = t
print(sys.getrefcount(t))
del t
print(sys.getrefcount(t1))
del t1
# print(sys.getrefcount(t1))  没有人引用测不出来

2:引用计数增加的情况:创建对象+1,对象被引用+1,对象被作为参数传递到函数中+2 因为globals ,func_globals 各存储一个对象
当对象被当做某个容器对象的元素的时候+1。

3:引用计数减少的场景:析构方法,对象的别名被赋予新的对象,离开所在的作用域,从对象所在的容器中删除,、

4:循环引用的问题内存泄漏:图解

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: json_steve
import objgraph


class Person(object):
    pass


class Dog(object):
    pass

p = Person()
d = Dog()

p.pet = d
d.master = p

del p
del d
print(objgraph.count('Person'))
print(objgraph.count('Dog'))

# 创建的对象实例并不会删除,没有办法回收自动释放,内存泄漏

循环引用

引用计数的补充垃圾回收机制解决循环引用问题:
1:底层原理:搜集所有的容器对象(可以再引用其他对象的对象),通过双向链表进行引用
每个容器对象通过一个变量gc_refs来记录当前的引用计数
对于每个容器对象,找到他引用的容器对象,并将这个容器对象的引用计数-1
如果此时引用计数是0,就可以被回收了。
垃圾回收
垃圾回收很耗时耗能—所以分代回收
思想:如果一个对象经过多次检测都没有回收他,那就减少他的使用频率。
机制:默认一个对象被创建出来后属于0代
如果经历垃圾回收后依然存活,则进入下一代
垃圾回收的周期顺序为:0代回收一定次数会触发0代和1代回收 默认10次
1代回收一定次数会触发0,1,2代回收 默认10次
触发垃圾回收机制:自动: 开启垃圾回收机制时(默认),只有当新增对象的数目-消亡对象的数目达到一定得阈值的时候才会触发垃圾检测。gc模块。默认700
手动添加一个垃圾回收,与自动垃圾回收是否开启无:gc.collect()
注意:1:在python2中如果循环引用的对象只要有一个实现了析构方法,垃圾回收就不会释放对象。在这种情况下为了
避免循环引用,容器类对象之间的应用考虑用弱引用,因为弱引用并不会引起引用计数+1。

性能调优可能用到objgraph。

查看分代回收参数

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: json_steve
import gc

print(gc.get_threshold())
# (700, 10, 10)   阈值  0代回收10次出发0,1代    1代回收10次回出发0,1,2代
# gc.set_threshold(200, 5, 5)

手动垃圾回收

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: json_steve

import objgraph
import gc


class Person(object):
    def __del__(self):
        print('person 对象被释放了')


class Dog(object):
    def __del__(self):
        print('dog对象被释放了')

p = Person()
d = Dog()

p.pet = d
d.master = p
del p
del d
gc.collect()  # 参数为0代回收1代回收2代回收 默认全部

print(objgraph.count('Person'))
print(objgraph.count('Dog'))
# 在python2中如果循环引用的对象只要有一个实现了析构方法,垃圾回收就不会释放对象,可以考率弱引用或者弱字典。

弱引用解决循环引用

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: json_steve


import objgraph
import gc
import weakref
# weakref.WeakKeyDictionary  弱字典
# weakref.WeakValueDictionary


class Person(object):
    def __del__(self):
        print('person 对象被释放了')


class Dog(object):
    def __del__(self):
        print('dog对象被释放了')

p = Person()
d = Dog()

p.pet = weakref.ref(d)
d.master = weakref.ref(p)
del p
del d
gc.collect()  # 参数为0代回收1代回收2代回收 默认全部

print(objgraph.count('Person'))
print(objgraph.count('Dog'))
# 在python2中如果循环引用的对象只要有一个实现了析构方法,垃圾回收就不会释放对象,可以考率弱引用或者若字典,因为弱引用不会让引用计数+1。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值