Python是一个对象(object),每个对象可能有多个属性(attribute)。Python属性有统一的管理方案。__dict__ofAttributes一个系统对象的属性可能来自它的类定义,称为类属性。类属性可能来自类定义本身,也可能继承自类定义。对象的属性也可以由对象实例来定义,称为对象属性。对象属性存储在对象的__dict__属性中。__dict__是一个字典,key是属性名,对应的value是属性本身。让我们看看下面的类和对象。鸡类继承自鸟类,summer是鸡类的一个对象。classbird(object):feather=Trueclasschicken(bird):fly=Falsedef__init__(self,age):self.age=agesummer=chicken(2)print(bird.__dict__)print(chicken.__dict__)print(summer.__dict__)下面对于我们的输出:{'__dict__':,'__module__':'__main__','__weakref__':,'feather':True,'__doc__':None}{'fly':False,'__module__':'__main__','__doc__':None,'__init__':}{'age':2}第一行是bird类属性,例如羽毛。第二行是小鸡类的属性,比如fly和__init__方法。第三行是夏天对象的属性,也就是年龄。有些属性,比如__doc__,不是我们定义的,而是Python自动生成的。另外,鸟类还有一个父类,就是对象类(就像我们的鸟定义,classbird(object))。这个对象类是Python中所有类的父类。可以看出Python中的属性是分层定义的,比如分为四层:object/bird/chicken/summer。当我们需要调用某个属性时,Python会一层层往上遍历,直到找到那个属性。(某个属性可能出现在不同的层次,被重复定义,Python在向上的过程中,会选择最先遇到的,即下层的属性定义)。当我们有一个summer对象的时候,我们可以分别查询summer对象,chicken类,bird类,object类的属性,然后我们就可以知道summer对象的所有__dict__,我们可以找到所有可以的属性通过对象summer进行调用和修改。下面两种属性修改方式是等价的:summer.__dict__['age']=3print(summer.__dict__['age'])summer.age=5print(summer.age)(上面的例子中,我们已经知道了summer的对象的类是鸡,鸡类的父类是鸟。如果只有一个对象,我们不知道它的类等信息,我们可以使用__class__属性来查找对象的类,然后调用类的__base__属性查询父类)attribute同一个对象的不同属性之间可能存在依赖关系。当一个属性被修改时,我们希望依赖于该属性的其他属性同时改变。这时候我们不能通过__dict__来静态存储属性。Python提供了多种方法来动态生成属性。其中之一称为属性。属性是特殊属性。例如,我们在鸡类中添加了一个成人特征。当对象年龄超过1时,adult为True;否则为False:classbird(object):feather=Trueclasschicken(bird):fly=Falsedef__init__(self,age):self.age=agedefgetAdult(self):ifself.age>1.0:returnTrueelse:returnFalseadult=property(getAdult)#propertyisbuilt-insummer=chicken(2)print(summer.adult)summer.age=0.5print(summer.adult)属性是使用内置函数property()创建的。property()最多可以加载四个参数。前三个参数是函数,分别用于处理查询特征、修改特征、删除特征。最后一个参数是特征的文档,可以是描述的字符串。我们用下面的例子来进一步说明::print("valuealsodeleted")delself.valueneg=property(getNeg,setNeg,delNeg,"I'mnegative")x=num(1.1)print(x.neg)x.neg=-22print(x.value)print(num.neg.__doc__)delx.neg上面的num是一个数字,neg是用来表示一个数的负数的特征。当一个数固定时,它的负数总是固定的;当我们修改一个数的负数时,它的值也应该改变。这两点是通过getNeg和setNeg来实现的。而delNeg的意思是如果属性neg被删除,应该做的操作就是删除属性值。property()的最后一个参数(“我是负数”)是负数属性的文档。使用特殊方法__getattr__我们可以使用__getattr__(self,name)查询动态生成的属性。当我们查询一个属性时,如果通过__dict__方法找不到该属性,那么Python会调用对象的__getattr__方法来动态生成该属性。例如:classbird(object):feather=Trueclasschicken(bird):fly=Falsedef__init__(self,age):self.age=agedef__getattr__(self,name):ifname=='adult':ifself.age>1.0:returnTrueelse:returnFalseelse:raiseAttributeError(name)summer=chicken(2)print(summer.adult)summer.age=0.5print(summer.adult)print(summer.male)每个属性需要有自己的处理函数,__getattr__可以是All即时属性在同一函数中处理。__getattr__可以根据函数名处理不同的属性。例如,当我们查询上面的属性名称male时,引发AttributeError。(Python中还有一个__getattribute__特殊方法用于查询任意属性,__getattr__只能用来查询不在__dict__体系中的属性)__setattr__(self,name,value)和__delattr__(self,name)可以用来修改和删除属性。它们更通用,可用于任意属性。其他动态生成属性的方法还有其他动态生成属性的方法,比如描述符(描述符类实际上是property()函数的底层,property()实际上创建了这个类的一个对象).如果您有兴趣,可以进一步查看。总结__dict__分层存储属性。每一层的__dict__只存储该层的新属性。子类不需要在父类中重复存储属性。动态生成属性是一个值得理解的概念。在Python开发中,您可能会使用这种方式来更合理地管理对象的属性。