做爲面對對象的核心內容,將從如下一個方面進行總結:
1. property和@property
2. __getattribute__()、__getattr__()、__setattr__()、__delattr__()
3. 描述符__get__()、__set__()、__delete__()
4. 不可變對象的實現
仍是直接上代碼來的方便node
property()用法函數
#coding = utf-8 class property_test: def __init__(self, size=10): self.size=size def __getsize__(self): return self.size def __setsize__(self, value): self.size = value def __deletesize__(self): del self.size x= property(__getsize__, __setsize__, __deletesize__) if __name__ == "__main__": p = property_test() p.x = 20 print (p.size) >>> 20
@property用法spa
#coding = utf-8 '''class property_test: def __init__(self, size=10): self.size=size def __getsize__(self): return self.size def __setsize__(self, value): self.size = value def __deletesize__(self): del self.size x= property(__getsize__, __setsize__, __deletesize__) ''' class property_test: def __init__(self, size=10): self.sizevalue=size #特別注意sizevalue不要和size同名 @property def size(self): return self.sizevalue @size.setter def size(self, value): self.sizevalue = value @size.deleter def size(self): del self.sizevalue if __name__ == "__main__": p = property_test() p.size = 20 p.size += 20 print (p.size, p.sizevalue)
屬性查找過程:code
__getattribute__ >>>> __dict__ >>>> __slots__ >>>> __getattr__orm
主要注意__getattr__的用法和無限遞歸錯誤對象
__getattr__在實例以及對應的__dict__中查找屬性失敗,那麼會調用__getattr__函數blog
防止無限遞歸錯誤能夠使用如下兩種方法:遞歸
1. self.__dict__[name] = value
2. super().__setattr__(name,value)utf-8
例:get
class rectange: def __init__(self, width=20, height=40): self.width = width self.height = height def __getattr__(self, name): return self.width def __setattr__(self,name, value): if name == "squ": super().__setattr__(name,value) super().__setattr__("width",40) super().__setattr__("height",40) print (name, self.__dict__[name]) else: #self.__dict__[name] = value super().__setattr__(name,value) print (name, self.__dict__[name]) if __name__ == "__main__": p = rectange() p.width = 10 p.squ = 80 print (p.width, p.height)
描述符說的直白點就是一個「綁定行爲」的對象屬性,經過__get__()、__set__()和__delete__()函數重寫描述符屬性
若是上述方法被定義在一個對象中,那麼這個對象就是一個描述符
當定義擁有者類時,每一個修飾符對象都是修飾符類的實例,綁定在類級別的屬性上
方法的原型爲:
① __get__(self, instance, owner)
② __set__(self, instance, value)
③ __del__(self, instance)
class A: def __init(self): self.color = "red" def __get__(self, instance, owner): print ("get instance:", instance) print ("get owner:", owner) return self.color def __set__(self, instance, value): print ("set instance:", instance) print ("set value:", value) self.color = value def __delete__(self, instance): print ("delete instance:", instance) del self.color class B: a = A() def __init__(self): self.color = "black" if __name__ == "__main__": b = B() b.a = "blue" b.color = b.a del b.a
首先說明下__slots__方法,具體能夠查看https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868200605560b1bd3c660bf494282ede59fee17e781000
方法:
1. 把__slots__設爲惟一容許操做的屬性,這會使得對象內部的__dict__再也不有效並阻止對其餘屬性的訪問
2. 在__init__中調用基類的__setattr__實現
3. 在__setattr__中拋出異常
例:
#coding=utf-8 class student: __slots__ = ("name") def __init__(self, name): super().__setattr__("name", name) self.name = name print (self.name) def __str__(self): return "{0.name}".format(self) def __setattr__(self, name, value): raise Exception(" '{__class__.__name__}' has no\ attribute '{name}'".format(__class__=self.__class__,name=self.name)) if __name__ == "__main__": s = student("zhanglin") #s.name = "lizhi"
__slot__定義類中能夠被外界訪問的屬性,相似node中的exports。當父類中定義了__slot__時,不能向父類中添加屬性。若是子類中沒有定義__slot__,則子類不受父類__slot__定義的限制。
若是父類與子類中都定義了__slot__,則影響的結果爲父類與子類__slot__的合集。