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

Python中属性的实现原理及其实现纯Python版

时间:2023-03-26 12:50:33 Python

起始属性是Python的一个内置函数,常用于以访问属性的方式修改类方法和调用函数。类C(对象):def__init__(self):self._x='Tom'@propertydefx(self):returnself._x@x.setterdefx(self,value):self._x=valuec=C()print(c.x)#Tomc.x='Tony'print(c.x)#Tonyproperty的实现虽然是C实现,但是仍然不妨碍对其实现原理的探索,其纯Python版本将在本文结束完成。描述符对象调用函数以访问属性。在这里,描述符对象将作为本文的起点。当一个类定义了__get__方法时,可以通过它的方法名直接调用__get__,例如:classDesc:def__init__(self,name):self.name=namedef__get__(self,obj,objtype):print('Retrieving',self.name)returnself.nameclassA:x=Desc('Tom')a=A()print(a.x)#Printed'Retrieving'这样看来,如果我们自己实现property,那就是一个类而不是一个函数。同样,为了能够完成对属性的赋值,类必须设置__set__函数。setter函数的实现这个实现需要换个思路。对于修饰符@x.setter,因为x已经是property()的一个实例,所以我们要完成的属性必须实现setter函数,那么函数体是什么呢?函数体也返回一个描述符对象,对象有__set__。property不就够了吗,所以这里的处理方式是setter函数会返回一个新的property实例。property的简单实现就是基于上面的分析。对于开头示例代码的简单版本:classproperty:def__init__(self,fget=None,fset=None):self.fget=fgetself.fset=fsetdef__get__(self,inst,owner=None):如果inst为None:returnselfreturnself.fget(inst)def__set__(self,inst,value):self.fset(inst,value)defsetter(self,fset):returnproperty(self.fget,fset)这基本上是一个基于C实现的纯Python版本,纯C实现在文件Objects/descrobject.c中。Python实现版:classproperty:"EmulatePyProperty_Type()inObjects/descrobject.c"def__init__(self,fget=None,fset=None,fdel=None,doc=None):self.fget=fgetself.fset=fsetself.fdel=fdelifdocisNoneandfgetisnotNone:doc=fget.__doc__self.__doc__=docdef__get__(self,obj,objtype=None):如果obj为None:如果self.fget为None:raiseAttributeError("unreadableattribute")returnself.fget(obj)def__set__(self,obj,value):如果self.fset为None:raiseAttributeError("can'tsetattribute")self.fset(obj,value)def__delete__(self,obj):如果self.fdel为None:raiseAttributeError("can'tdeleteattribute")self.fdel(obj)defgetter(self,fget):返回类型(self)(fget,self.fset,self.fdel,self.__doc__)defsetter(self,fset):返回类型(self)(self.fget,fset,self.fdel,self.__doc__)defdeleter(self,fdel):returntype(self)(self.fget,self.fset,fdel,self.__doc__)用于创建新的属性实例类型(self)(...),因为考虑到属性可能被继承,属性主要取决于描述符机制。内置属性也成为Python的一个特性。其内部实现原理非常简单,但应用起来非常方便,可读性强。