面向對象學習(四)

運算符重寫 #encoding=utf-8 class Vector(object): def __init__(self,a,b): self.a = a self.b = b def __str__(self): return "Vector(%d,%d)" %(self.a,self.b) def __add__(self,other): return Vector(self.a + other.a,self.b + other.b) x = Vector(3,7) y = Vector(1,-10) print(x + y) print(str(x)) 類的特殊成員 1.__doc__ 類的描述信息 #encoding=utf-8 class Vector(object): """類的描述信息""" def __init__(self): pass v = Vector() print(v.__doc__) 2. __module__ 和 __class__ ➢ __module__ 表示當前操作的對象在那個模塊 ➢ __class__ 表示當前操作的對象的類是什麼 3.__del__ 析構方法,當對象在內存中被釋放時,自動觸發執行。 注:此方法一般無須定義,因爲Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因爲此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。 >>> class P(): ... def __del__(self): ... print("del exe") ... >>> p = P() >>> del p del exe 4. __call__ 對象後面加括號,觸發執行。 注:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()() #encoding=utf-8 class Foo(object): def __init__(self): pass def __call__(self,*args,**kwargs): print("__call__") obj = Foo() obj()#會調用實例的__call__方法 5. __dict__ 類或對象中的所有成員 6. __str__ 如果一個類中定義了__str__方法,那麼在打印 對象 時,默認輸出該方法的返回值。 >>> class Foo(object): ... def __str__(self): ... return "__str__被調用" ... >>> obj = Foo() >>> print(obj) __str__被調用 7. __getitem__ 、__setitem__ 、__delitem__ 用於索引操作,如字典。以上分別表示獲取、設置、刪除數據 #encoding=utf-8 class Foo(object): def __getitem__(self,key): print("__getitem__",key) def __setitem__(self,key,value): print("__setitem__",key,value) def __delitem__(self,key): print("__delitem__",key) obj = Foo() result = obj["k1"]#自動調用 __getitem__ obj['k2'] = 'kkkk'#自動調用 __setitem__ del obj["k1"]#自動調用 __delitem__ 8. __getslice__、__setslice__、__delslice__ 在python 2.7可以使用,在3.x已經被去掉了,需要使用__getitem__、__setitem__、__delitem__和__getslice__來實現 #encoding=utf-8 class Foo(object): def __init__(self,name,age): self.name = name self.age = age self.li = [1,2,3,4,5,6,7] def __getitem__(self,item): if isinstance(item,slice): return self.li[item] elif isinstance(item,int): return self.li[item] def __setitem__(self,key,value): print(key,value) self.li[key] =value def __delitem__(self,key): print(key) del self.li[key] a = Foo("alex",18) print(a[3:5])#自動調用__getitem__ a[0] = 100#自動調用__setitem__ print(a[0])#自動調用__getitem__ del a[0]#自動調用__delitem__ print(a[0])#自動調用__getitem__ 9.__iter__ 用於迭代器,之所以列表、字典、元組可以進行for循環,是因爲類型內 部定義了 __iter__ #encoding=utf-8 class Foo(object): def __init__(self,sq): self.sq = sq def __iter__(self): return iter(self.sq) obj = Foo([1,2,3,4,5]) for i in obj: print(i) 10.__slot__ 限制實例可以使用的屬性名稱 #encoding=utf-8 class Student(object): __slots__ =("name","age")# 用tuple定義允許綁定的屬性名稱 s = Student() s.name = "hhh" s.age = 25 s.score = 99 11. __new__ __new__() 方法是在類準備將自身實例化時調用。 __new__() 方法始終都是類的靜態方法,即使沒有被加上靜態方法裝飾器。 #encoding=utf-8 class A(object): def __init__(self): print("init") def __new__(cls,*args,**kwargs): print("new %s" %cls) return object.__new__(cls,*args,**kwargs) A() 結果分析: 首先調用__new__()方法實例化類,產生類的實例對象; 然後實例對象調用__init__()方法; 繼承自object的新式類纔有__new__。 __new__至少要有一個參數cls,代表要實例化的類,此參數在實例化時由Python解釋器自動提供。 __new__必須要有返回值,返回實例化出來的實例,這點在自己實現__new__時要特別注意,可以return父類__new__出來的實例,或者直接是object的__new__出來的實例。 __init__有一個參數self,就是這個__new__返回的實例,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要返回值。若__new__沒有正確返回 當前類 cls的實例,那__init__是不會被調用的,即使是父類的實例也不行。 __new__ 、 __init__區別 __new__() 類實例化時候調用,產生類的實例 __init__() 類實例對象產生後調用,用來初始化對象的數據 單例 #encoding=utf-8 class Singleton(object): def __new__(cls,*args,**kwargs): if not hasattr(cls,"_instance"): orig = super(Singleton,cls) cls._instance = orig.__new__(cls,*args,**kwargs) return cls._instance class MyClass(Singleton): a = 1 one = MyClass() two = MyClass()#one 和 two 完全相同 two.a = 3 print(one.a) print(id(one)) print(id(two)) print(one == two) print(one is two) python對象銷燬(垃圾回收) 同Java語言一樣,Python使用了引用計數這一簡單技術來追蹤內存中的對象。在Python內部記錄着所有使用中的對象各有多少引用。一個內部跟蹤變量,稱爲一個引用計數器。當對象被創建時,就創建了一個引用計數,當這個對象不再需要時,也就是說,這個對象的引用計數變爲0 時,它被垃圾回收。但是回收不是"立即"的,由解釋器在適當的時機,將垃圾對象佔用的內存空間回收 >>> import sys >>> print(sys.getrefcount(8787)) 3 >>> a = 8787 >>> print(sys.getrefcount(a)) 2 >>> b = a >>> print(sys.getrefcount(a)) 3 >>> c = a >>> print(sys.getrefcount(a)) 4 >>> d = c >>> print(sys.getrefcount(a)) 5 >>> [1,2].append(a) >>> print(sys.getrefcount(a)) 5 >>> del d >>> print(sys.getrefcount(a)) 4 >>> del b >>> print(sys.getrefcount(a)) 3 >>> del a >>> print(sys.getrefcount(a)) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined 垃圾回收 垃圾回收機制不僅針對引用計數爲0的對象,同樣也可以處理循環引用的情況。循環引用指的是,兩個對象相互引用,但是沒有其他變量引用他們。這種情況下,僅使用引用計數是不夠的。Python 的垃圾收集器實際上是一個引用計數器和一個循環垃圾收集器。作爲引用計數的補充,垃圾收集器也會留心被分配的總量很大(及未通過引用計數銷燬的那些)的對象。在這種情況下,解釋器會暫停下來,試圖清理所有未引用的循環。析構函數 __del__ ,__del__在對象銷燬的時候被調用,當對象不再被使用時,__del__方法運行: #encoding=utf-8 class Point(object): def __init__(self,x=0,y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print(class_name,"銷燬") pt1 = Point() pt2 = pt1 pt3 = pt1 print(id(pt1),id(pt2),id(pt3)) del pt1 print(pt2) print(pt3) del pt2 print(pt3) del pt3 print(pt3) 循環引用的對象被銷燬 #encoding=utf-8 class LeakTest(object): def __init__(self): self.a = None self.b = None print("object = %d born here" %id(self)) A = LeakTest() B = LeakTest() A.a = B B.b = A import sys print(sys.getrefcount(A)) print(sys.getrefcount(B)) del A try: print(sys.getrefcount(A)) except Exception as e: print(e) del B try: print(sys.getrefcount(B)) except Exception as e: print(e)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章