当前位置: 首页 > 后端技术 > Python

python-object-oriented-19-object根类-weakref弱引用

时间:2023-03-26 00:56:49 Python

1。对象根类对象类是所有类的父类,所以所有类都具有对象类的属性和方法。我们显然需要深入研究对象类的结构。深入学习Python对我们来说是非常有好处的。其实我们在第十七讲介绍继承的时候,已经介绍了部分对象根类,包括使用mro()函数查看类的继承关系。这次我们将从另一个角度来解释对象根类。还是先举个例子:classPerson:count=0def__init__(self,name,age):self.name=nameself.age=agedefsay_age(self):print("{0}的年龄是:{1}".format(self.name,self.age))obj=object()print(dir(obj))s=Person("聂法军",100)print(dir(s))运算结果:['__class__','__delattr__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__gt__','__hash__','__init__','__init_subclass__','__le__','__lt__','__ne__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__']['__class__','__delattr__','__dict__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__gt__','__hash__','__init__','__init_subclass__','__le__','__lt__','__module__','__ne__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','__weakref__','age','count','name','say_age']程序说明:这个过程序列已经很熟悉了,所以我不再详细介绍操作原理。我们对比对象obj和对象s返回的属性列表,发现增加了几个属性:__dir__,__module__,__weakref__,age,count,name,say_age。首先简单一点:实例属性:name,年龄类属性:count实例方法:say_age2。__dir__属性列表只有类方法(静态方法)、类属性、实例属性、实例方法中至少有一个,才会有_dict__属性。和上面例子中的对象obj一样,没有__dict__属性。3、__module__模块属性表示当前对象运行的模块类Person:passp=Person()print(p.__module__)运行结果:__main__程序说明:默认运行在__main__模块下。4.__weakref__弱引用属性说到弱引用,就不得不说说上面提到的Python垃圾回收机制。垃圾回收机制的核心机制是引用计数。weakref的弱引用是相对于引用计数而言的。引用计数的方法也可以称为正则引用或强引用(个人定义稍后,如有错误请指教。)相同点:无论是正则引用还是弱引用,都是被引用对象的地址可以参考获得。也就是说,它可以对被引用对象有期望的操作差异:常规引用会增加引用计数,而弱引用不会增加引用对象。默认没有弱引用:classPerson:passp=Person()print(p.__weakref__)运行结果:无程序说明:普通对象默认没有弱引用。下面我们将介绍弱引用的两种常见形式4.1weakref.ref(p_object)方法使用weakref.ref方法是最常规的方法,它返回一个weakref类型的对象。如果只需要使用引用,则需要通过()来获取被引用的对象。示例代码:importweakrefimportsysclassPerson:def__init__(self,name,age):self.name=nameself.age=agedefref_callback(reference):print("ref_callback")print(reference,"thisweakreferenceinvalid")p1=Person("聂法军",100)print(sys.getrefcount(p1))#使用weakref.ref方法构造弱引用wek1=weakref.ref(p1,ref_callback)print(sys.getrefcount(p1))print("--"*20)print(p1.__weakref__)print(wek1)print(wek1())print("{0}的年龄是:{1}".format(wek1().name,wek1().age))print('--'*20)delp1print(wek1)运行结果:22-------------------------------------------<0x00000260D5978CC8处的弱引用;到0x00000260BE779908处的“人”><0x00000260D5978CC8处的弱引用;to'Person'at0x00000260BE779908><__main__.Personobjectat0x00000260BE779908>聂发俊的年龄是:100-------------------------------------ref_callback这个弱引用无效程序说明:第一部分两部分的引用数都是2(为什么是2,可以看之前的垃圾垃圾收集机制),说明弱引用不会增加引用计数。创建弱引用后,被引用对象的__weakref__也有值,指向与wek1相同的地址。wek1是weakref类型的对象。只有使用wek1()才能得到引用对象__main__.Person。使用被引用对象的实例属性在删除被引用对象时也需要带上(),会触发构造弱引用指定的回调函数ref_callback,同时wek1的弱引用状态变为死状态。4.2weakref.proxy(p_object,callback)方法使用weakref.proxy方法创建一个弱引用并返回被引用的对象,类似于a=b操作,这点与使用ref函数不同。示例代码:importweakrefimportsysclassPerson:def__init__(self,name,age):self.name=nameself.age=agedefproxy_callback(reference):print("proxy_callbackcall")p1=Person("聂法君",100)print(sys.getrefcount(p1))#使用weakref.proxy方法构建弱引用wek2=weakref.proxy(p1,proxy_callback)print(sys.getrefcount(p1))print("--"*20)print(p1)print(wek2)print("{0}的年龄是:{1}".format(wek2.name,wek2.age))print('--'*20)delp1print(wek2)结果:22--------------------------------------<__main__.Person对象在0x0000010E9784F388><__main__.Personobjectat0x0000010E9784F388>聂法军年龄为:100-------------------------------------proxy_callbackcallTraceback(mostrecentcalllast):File"test.py",line30,inprint(wek2)ReferenceError:weakly-referencedobjectnolongerexists程序描述:引用计数的数量是与上面使用weakref的示例相同。proxy返回的引用对象,p1和wek2指向同一个地址0x000001EFF7219908,使用实例属性不需要()删除引用对象p1时,会调用方法weakref.proxy指定的回调函数proxy_callback,注意,因为引用的对象是第一个删除,然后执行回调函数。此时虽然有参数reference指向被引用对象,但是不能使用,因为已经被删除了。此时打印wek2会提示错误信息,因为引用的对象p1已经被删除,无法获取该对象4.3弱引用小结weakref.ref()返回weakref,引用对象需要借助使用()。当被引用的对象被删除时,weakref的状态就变成了死亡。引用对象,当删除引用对象时,不能再使用代理,也不能再获取引用对象。目前实际开发中并没有使用到弱引用,具体使用场景后续会补充。备注:更多精彩博客请访问:聂法军技术博客对应视频教程请访问:python400完整markdown笔记请访问:python400_learn_github