python GC(Garbage collection )、属性访问拦截器、getattribute()

来源:互联网 发布:单片机采样频率 编辑:程序博客网 时间:2024/06/07 00:56

GC垃圾回收

python以引用计数机制为主,标记-清除和分代收集两种机制为辅的策略。
python引用机制:一旦没有引用,内存就直接释放了,不用向其他机制等到特定时机:处理回收内存的时间分摊到了平时
缺点:维护引用计数消耗资源,循环引用:对于循环引用的对象无法回收,会造成内存的大量浪费

Ruby and Python GC
visualizing gargabge collection in ruby and python


GC的工作:

1 为新生成的对象分配内存 

2 识别那些垃圾对象,并且从垃圾对象那回收内存

#Garbage collection(GC垃圾回收)import gcprint(gc.get_threshold())  #(700,10,10)#第一个参数700  表示已创建的对象的个数-已回收的对象的个数>700,则进行0代链表的清零#第二个参数10  说明每清理10次0代链表,清理一次1代链表,顺便清理一次0代链表#第三参数10 说明每清理10次1代链表,清理一次2代链表,顺便清理一次0 1代链表print(gc.get_count())#(542,10,10) 获取当前自动执行垃圾回收的计数器

gc模块的自动垃圾回收机制
主要作用就是发现并处理不可达的垃圾对象
垃圾回收=垃圾检查+垃圾回收
在python中,采用分代收集的方法,把对象分为三代,一开始,对象在创建的时候,放在一代中,如果在一次一代的垃圾检查中,该对象存活下来,
就会被放到二代中,同理在一次二代的垃圾检查中,该对象存活下来,就会被放到三代中。

python的垃圾回收

1 程序运行后会自动垃圾回收
2 GC垃圾回收
3 手动垃圾回收,gc.collcec()


python 的垃圾回收的bug

python的所有垃圾回收都是调用__del__()方法,若是将__del__()方法进行了重写,则会出现垃圾无法回收
若非要重写__del__(),最后再加上默认父类的调用


引用计数加1
1 对象被创建 a=23
2 对象被引用 b=a
3 对象被作为参数,传入到一个函数中 func(a)
4 对象作为一个元素,存储在容器中 list1=[a,a]


引用计数-1
1 对象的别名被显示销毁 del a
2 对象的别名被赋予新的对象,a=24
3 一个对象离开它的作用域 ,f函数执行完毕,f函数中的局部变量(全局变量不会)
4 对象所在的容器被销毁,或从容器中删除对象


import sysaa="hello world"print(sys.getrefcount(aa)) #返回引用数,getrefcount()相当于+1,函数引用class ClassA():def __init__(self):print("object born,id :%s"%str(hex(id(self))))def f2():while True:c1=ClassA()c2=ClassA()c1.t=c2c2.t=c1del c2 del c1f2()#这里系统会最后产生很多循环引用,如果把gc关闭后gc.collect()#手动进行垃圾回收#1 程序运行后会自动垃圾回收#2 GC垃圾回收#3 手动垃圾回收,gc.collcec()#python 的垃圾回收的bug#python的所有垃圾回收都是调用__del__()方法,若是将__del__()方法进行了重写,则会出现垃圾无法回收#若非要重写__del__(),最后再加上默认父类的调用

属性访问拦截器

class Itcast(object):def __init__(self,subject1):self.subject1=subject1self.subject2="cpp"#属性访问时拦截器#def __getattribute__(self,obj):def __getattribute__(self,obj):print("====1>%s"%obj)if obj=='subject1':print("log subject1")return "redirect python"else:temp=object.__getattribute__(self,obj) #调用父类的getattribute()print("====2>%s"%str(temp))return tempdef show(self):print("this is Itcast")#类中访问属性的地方先运行__getattribute__方法s=Itcast("python")print(s.subject1)print(s.subject2)s.show()#首先调用一下show,temp得到show()方法,接着调用#可以看出:在调用方法时:1 先获取show属性对应的结果,结果应该是个方法#                        2 调用方法  方法()#                        #调用方法也是先调用属性,这个属性指向方法,再调用#一个方法其实是一个方法名执向方法定义的方法体#'''显示结果====1>subject1log subject1redirect python====1>subject2====2>cppcpp====1>show====2><bound method Itcast.show of <__main__.Itcast object at 0x000000000114CF60>>  #方法this is Itcast'''#可以看出,====2>这里返回了一个方法,temp

使用getattribute()注意其中不要有self.属性

#这里有个陷阱class Person(object):def __getattribute__(self,obj):print("---test---")if obj.startswith("a"):return "comeon"else:return self.test#这里的self.test是得到类的属性,访问对象的属性先进行__getattribute__().再次进入__getattribute__()....再次进入#在getattribute中禁止调用self.属性def test(self):print("OK")t=Person()t.at.b  #程序死掉,其中的self是这里的t#方法也是属性





原创粉丝点击