使用內置數據結構和算法 python
當你實現很是小的的Python程序時,你可能會看到由你的代碼的算法複雜性而形成的減速。 這個一般不是Python語言自己速度的形成,這更有多是由於沒有爲您的問題使用最好的算法和數據結構。幸運的是Python標準庫有許多內置的算法和數據結構能夠使用。除了速度,使用這些經常使用的算法和數據結構可讓你的生活更輕鬆。 你可能想使用的一些更有力的工具,這是一個棘手的問題。 避免從新實現經常使用功能將會節省您的時間。算法
Double-ended Queue(雙端隊列)
deque類是在collections模塊中,它是一個double-ended隊列。從deque隊列開始或者結尾,插入或者刪除會花費相同的時間。這個使其成爲先進先出(FIFO)隊列的理想選擇。數據結構
fifo = deque() fifo.append(1) # Producer x = fifo.popleft() # Consumer
內置List也能夠實現有序隊列,如fifo。但內置List從列表頭部的插入或刪除項,花費時間是線性的,這比常數慢得多。app
Ordered Dictionary(有序字典)
標準字典是無序的。 這意味着具備相同的鍵和值的dict能夠有不一樣的迭代次序。 這種行爲有一個使人驚訝的副產品就是實現字典的快速哈希表。dom
a = {} a['foo'] = 1 a['bar'] = 2 # Randomly populate ‘b’ to cause hash conflicts while True: z = randint(99, 1013) b = {} for i in range(z): b[i] = i b['foo'] = 1 b['bar'] = 2 for i in range(z): del b[i] if str(b) != str(a): break print(a) print(b) print('Equal?', a == b) >>> {'foo': 1, 'bar': 2} {'bar': 2, 'foo': 1} Equal? True
collections模塊中的OrderedDict類是一種特殊類型的字典,它跟蹤其鍵的插入順序。 迭代鍵OrderedDict具備可預測的行爲。 這能夠大大簡化測試和調試經過使全部代碼肯定性。數據結構和算法
a = OrderedDict() a['foo'] = 1 a['bar'] = 2 b = OrderedDict() b['foo'] = 'red' b['bar'] = 'blue' for value1, value2 in zip(a.values(), b.values()): print(value1, value2) >>> 1 red 2 blue
Default Dictionary
字典對記帳和跟蹤統計很是有用。內建的字典類型是不能假設任何鍵已經存在。 這使得它作一些簡單的事情時顯得笨拙,如增長一個存儲在字典中的計數器。函數
stats = {} key = 'my_counter' if key not in stats: stats[key] = 0 stats[key] += 1
collections模塊中的defaultdict類簡化了當key不存在時自動存儲默認值。 全部你須要作的是提供每次鍵丟失時將返回默認值的函數。 在這裏例如,int內置函數返回0如今,遞增計數器是
簡單。int()->0工具
stats = defaultdict(int) stats['my_counter'] += 1
Heap Queue
關於這裏,heap這種數據結構的介紹有一個簡單的blog能夠去看一下http://blog.csdn.net/minxihou/article/details/51857518
堆是用於維護優先級隊列的有用數據結構。 heapq模塊提供了在標準list類型中建立堆的功能使用函數heappush,heappop和nsmallest等函數。任何優先級的項能夠按任何順序插入堆中。測試
a = [] heappush(a, 5) heappush(a, 3) heappush(a, 7) heappush(a, 4)
老是先移除最高優先級(lowest number)的項..net
print(heappop(a), heappop(a), heappop(a), heappop(a)) >>> 3 4 5 7
生成的list在heapq以外很容易使用。 訪問堆的0索引將老是返回最小的項。
a = [] heappush(a, 5) heappush(a, 3) heappush(a, 7) heappush(a, 4) assert a[0] == nsmallest(1, a)[0] == 3
list的sort方法保持不變。
print('Before:', a) a.sort() print('After:' , a) >>> Before: [3, 4, 7, 5] After: [3, 4, 5, 7]
Bisection
調用index方法查找列表中的項須要花費與list長度成線性比例的時間。
x = list(range(10**6)) i = x.index(991234)
使用bisect模塊的方法,如:bisect_left,是使用二分查找的方法。它返回的索引是插入點值插入序列。
i = bisect_left(x, 991234)
二分搜索的複雜度是對數的。 這意味着使用bisect搜索100萬個項的list的速度是使用線性索引方式搜索的14倍。It’s way faster!
Iterator Tools
tertools內置模塊包含大量有用與迭代器相關的函數。不是全部這些都在Python 2中可用,但它們能夠輕鬆地使用經過查看模塊中記錄的simple recipes。 請參閱help(itertools)得到更多詳細信息。
itertools中的函數主要分爲三類:
Linking iterators together
•chain:將多個迭代器組合成一個順序迭代器。
•cycle:一直重複迭代器的項。
•tee:將單個迭代器拆分爲多個並行迭代器。
•zip_longest:內置zip函數的變體,當迭代的幾個對象長度不一樣的時候有更好的表現。
Filtering items from an iterator
•islice:經過數字索引切片迭代器,而不進行復制。
•takewhile:當斷言函數返回Ture時返回迭代器中的項。
•dropwhile:當斷言函數第一次爲False時,返回迭代器中的項。
•filterfalse:當斷言函數第一次爲False時,返回迭代器中全部的項。 與內置函數filter做用相反。
Combinations of items from iterators(組合迭代器中的項)
•product:返回迭代器中項的笛卡爾乘積,是一種很好的替代深層嵌套列表推導的方法。
•permutations:返回長度爲N的有序排列迭代器。
•combination:返回長度爲N的,用迭代器中未重複項所組成的無序組合。
在itertools模塊中有更多的功能和recipes可用不能在這裏一一說起。 每當你發現本身處理一些棘手的迭代代碼,itertools文檔是值得再次查看,看看是否有你想要的東西。
Things to Remember
一、使用Python的內置模塊用於算法和數據結構。
二、不要本身從新實現此功能。