爲了解決原來基於深度優先搜索算法不知足本地優先級,和單調性的問題。 python2.3版本以後不論是新式類仍是經典類,查找繼承順序都採用C3算法
C3算法的本質就是Merge, 不斷地把mro()函數返回的隊列進行Merge,規則以下: (0) 首先把要查找的類的全部父類的mro找出來,再把全部父類的mro和全部父類進行歸併算法 (1) 若是第一個序列的第一個元素,是後續序列的第一個元素,或者在後續序列中沒有再次出現,則將這個元素合併到最終的方法解析順序序列中, 並從當前操做的所有序列中刪除。 (2) 若是不符合,則跳過此元素,查找下一個列表的第一個元素,重複1的判斷規則。
class A(object): pass class B(A): pass class C(A): pass class D(B): pass class E(C): pass class F(D,E): pass # F的mro順序: # 第一步 找出F全部的父類的MRO # D [DBAO] # E [ECAO] # 第二步 把全部父類的MRO 以及 全部的父類作歸併算法 # [DBAO] [ECAO] [DE] # F + merge([DBAO] [ECAO] [DE]) # 取第一個序列的第一個元素D,它是後續序列[DE]的第一個元素,那麼D是最終序列的第一個元素 # 把D從所有序列中刪除 # B在後續序列中沒有再次出現,那麼B是最終序列的第二個元素 # FD + merge([BAO] [ECAO] [E]) # A在後續序列中出現了,跳過A,查找下一個列表的第一個元素E,E是後續序列的第一個元素,取E # FDB + merge([AO] [ECAO] [E]) # FDBE + merge([AO] [CAO]) # FDBEC + merge([AO] [AO]) # FDBECAO print(F.__mro__)
python中的垃圾回收機制是:引用計數主、標記清除和分代回收爲輔 python裏每個東西都是對象,它們的核心就是一個結構體:PyObject Python對象和引用是分離的 PyObject是每一個對象必有的內容,其中ob_refcnt就是作爲引用計數。當一個對象有新的引用時,它的ob_refcnt就會增長,當引用它的對象被刪除, 它的ob_refcnt就會減小。 當引用計數爲0時,該對象生命就結束了,就會被清除了。 查看某個變量的引用計數 from sys import getrefcount print(getrefcount(變量)) 引用計數機制的優勢: 1. 簡單 2. 實時性 一旦沒有引用,內存就直接釋放了。不用像其餘機制等到特定時機。實時性還帶來一個好處:處理回收內存的時間分攤到了平時。 引用計數機制的缺點: 1. 維護引用計數消耗資源 2. 循環引用的時候,這個對象的引用計數永遠不會爲0,這個對象就會一直存在 d = [1,2,3] f = [4,5,6] d.append(f) f.append(d)
標記清除(Mark—Sweep)算法是一種基於追蹤回收(tracing GC)技術實現的垃圾回收算法。 它分爲兩個階段: 第一階段是標記階段,GC會把全部的活動對象打上標記。 第二階段是把那些沒有標記的非活動對象進行回收。 如何判斷哪些是活動對象哪些是非活動對象: 對象之間經過引用(指針)連在一塊兒,構成一個有向圖,對象構成這個有向圖的節點,而引用關係構成這個有向圖的邊。從根對象(root object)出發, 沿着有向邊遍歷對象,可達的(reachable)對象標記爲活動對象,不可達的對象就是要被清除的非活動對象。根對象就是全局變量、調用棧、寄存器。 示例圖:
在上圖中,咱們把小圈當作全局變量,也就是把它做爲root object, 從小圈出發,對象1可直達,那麼它將被標記,對象二、三、6可間接到達也會被標記, 而4和5不可達,那麼一、二、三、6就是活動對象,4和5是非活動對象會被GC回收。 標記清除算法做爲Python的輔助垃圾收集技術主要處理的是一些容器對象, 好比list、dict、tuple,instance等,由於對於字符串、數值對象是不可能形成循環引用問題。 Python使用一個雙向鏈表將這些容器對象組織起來。 不過,這種簡單粗暴的標記清除算法也有明顯的缺點:清除非活動的對象前它必須順序掃描整個堆內存,哪怕只剩下小部分活動對象也要掃描全部對象。
1. 理論解釋 分代回收是一種以空間換時間的操做方式,Python將內存根據對象的存活時間劃分爲不一樣的集合,每一個集合稱爲一個代,Python將內存分爲了3「代」,分別 爲年輕代(第0代)、中年代(第1代)、老年代(第2代),他們對應的是3個鏈表,它們的垃圾收集頻率與對象的存活時間的增大而減少。新建立的對象都會 分配在年輕代,年輕代鏈表的總數達到上限時,Python垃圾收集機制就會被觸發,把那些能夠被回收的對象回收掉,而那些不會回收的對象就會被移到中年 代去,依此類推,老年代中的對象是存活時間最久的對象,甚至是存活於整個系統的生命週期內。同時,分代回收是創建在標記清除技術基礎之上。分代回收 一樣做爲Python的輔助垃圾收集技術處理那些容器對象。 2. 簡單來講 python內存中存放了三代數據,每一代都是鏈表 0代 年輕的一代 域值(700, 10, 10) 當0代鏈表達到域值上限後,觸發0帶的回收 0代被觸發回收以後沒有被回收的對象放入1代 0代被回收10次的時候觸發1代回收 1代沒有被回收對象放入2代 1代觸發10次的時候觸發2代回收
當某個條件達到後,觸發了垃圾回收機制,首先在0代中先作引用計數,把引用爲0的對象清除,而後再作標記清除,把沒用的循環引用對象也清除, 再把沒有清除的對象放到1代,當觸發了10次0代回收機制後,會觸發1代的垃圾回收,而後先作引用計數,再作標記清除,觸發10次1代垃圾回收後, 會觸發2代垃圾回收...