標籤:它的 log 運行 表資料 常用 線性 建立 千萬 添加
這裡的內容僅僅是本人閱讀《Python高效能編程》後總結的一些知識,用於自己更好的瞭解Python機制。本人現在並不從事計算密集型工作:人工智慧、資料分析等。僅僅只是出於好奇而去閱讀這本書。很多人因為Python不能同時使用多顆CPU(全域解譯器鎖GIL),而覺得它不能實現高效能。書中有很多介紹避開GIL或者Python虛擬機器的方式,例如Cython,PyPy等。
首先我們要說一下時間複雜度,可以協助我們理解CPython編譯器怎麼幹活:
時間複雜度
在描述演算法複雜度時,經常用到o(1), o(n), o(logn), o(nlogn)來表示對應演算法的時間複雜度, 這裡進行歸納一下它們代表的含義: 這是演算法的時空複雜度的表示。不僅僅用於表示時間複雜度,也用於表示空間複雜度。O後面的括弧中有一個函數,指明某個演算法的耗時/耗空間與資料增長量之間的關係。其中的n代表輸入資料的量。比如時間複雜度為O(n),就代表資料量增大幾倍,耗時也增大幾倍。比如常見的遍曆演算法。再比如時間複雜度O(n^2),就代表資料量增大n倍時,耗時增大n的平方倍,這是比線性更高的時間複雜度。比如冒泡排序,就是典型的O(n^2)的演算法,對n個數排序,需要掃描n×n次。再比如O(logn),當資料增大n倍時,耗時增大logn倍(這裡的log是以2為底的,比如,當資料增大256倍時,耗時只增大8倍,是比線性還要低的時間複雜度)。二分尋找就是O(logn)的演算法,每找一次排除一半的可能,256個資料中尋找只要找8次就可以找到目標。O(nlogn)同理,就是n乘以logn,當資料增大256倍時,耗時增大256*8=2048倍。這個複雜度高於線性低於平方。歸併排序就是O(nlogn)的時間複雜度。O(1)就是最低的時空複雜度了,也就是耗時/耗空間與輸入資料大小無關,無論輸入資料增大多少倍,耗時/耗空間都不變。 雜湊演算法就是典型的O(1)時間複雜度,無論資料規模多大,都可以在一次計算後找到目標(不考慮衝突的話)
列表和元組 1、列表是動態數組,它們可變且可以重設長度(改變其內部元素個數)。2、元組是靜態數組,它們不可變,且其內部資料一旦建立便無法改變。3、元組緩衝與Python 運行時環境,這以為著我們每次使用元組都無需訪問核心去分配記憶體。 當建立的資料量及,達到百萬千萬級以上,合并多個元組,會比一個列表佔用更少的空間。 列表在進行append()操作時,會Copy原列表,建立一個更大的列表,然後銷毀原列表。在append時,編譯器會預建立一部分資料空間,用於以後的添加。元組在進行合併作業(+)時,會建立一個新的元組,然後銷毀舊的元組,元組資料集前後不會發生改變
字典和集合 字典和集合適合於儲存能夠被索引的資料。當你在使用字典和集合處理可以索引的資料時它的時間複雜度是O(1),但是對於那些不能被索引的資料是徒勞無功的。 字典與集合在CPython建立時,會像系統申請定量記憶體塊預設最小長度是8,每次改變大小增加到原來的4倍。每次插入資料時會產生索引(位元),會在申請的記憶體儲存塊中隨機插入,如果目標儲存塊已有資料,那就換個位置,這叫做散列碰撞。 由於字典與集合在插入資料不是每一次都會擴增集合體積,所以會比列表效率高效、省記憶體空間。雖然會有散列碰撞,但是每次散列碰撞都是位元的比較。 集合:在對一批資料進行去重時,不如把這批資料放入集合中。因為在你使用列表格儲存體這批資料時,你需要手動判斷是否重複,而且列表會預建立空桶用於存接下來的資料。而集合是一個純Key的數組,裡面的資料時唯一的。 字典:是key:value的形式儲存 散列函數:在散列函數中會對字典和列表產生位元作為掩碼(可以理解為索引,因為在插入、查詢時是依靠這個值)。 應該有一種——而且最好只有唯一的一種——明顯的方式去完成它。雖然這種方式可能一開始並不明顯,除非你是荷蘭人。——Tim PetersPython之禪使用Python的目的是快速實現功能,且代碼能夠穩定運行。至於最佳化,所花費的時間可能是產品初創到誕生的數倍時間。
《Python高效能編程》——列表、元組、集合、字典特性及建立過程