deque 是 double-ended queue的縮寫,類似於 list,不過提供了在兩端插入和刪除的操作。
例如:
queue = deque() # append values to wait for processing queue.appendleft("first") queue.appendleft("second") queue.appendleft("third") # pop values when ready process(queue.pop()) # would process "first" # add values while processing queue.appendleft("fourth") # what does the queue look like now? queue # deque(['fourth', 'third', 'second'])
作為一個雙端隊列,deque還提供了一些其他的好用方法,例如 rotate 等,下面我們一起來看一下:
填充
deque可以從任意一端填充,在python實作稱為「左端」和「右端」。
import collections d1 = collections.deque() d1.extend('abcdefg') print 'extend:', d1 d1.append('h') print 'append:', d1 d2 = collections.deque() d2.extendleft(xrange(6)) print 'extendleft', d2 d2.appendleft(6) print 'appendleft', d2
extendleft()迭代處理其輸入,對每個元素完成與appendleft()相同的處理。
extend: deque(['a', 'b', 'c', 'd', 'e', 'f', 'g']) append: deque(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']) extendleft deque([5, 4, 3, 2, 1, 0]) appendleft deque([6, 5, 4, 3, 2, 1, 0])
利用
可以從兩端利用deque元素,取決於應用的演算法。
import collections print "From the right:" d = collections.deque('abcdefg') while True: try: print d.pop(), except IndexError: break print print "\nFrom the left:" d = collections.deque(xrange(6)) while True: try: print d.popleft(), except IndexError: break print
使用pop()可以從deque右端刪除一個元素,使用popleft()可以從deque左端刪除一個元素。
From the right: g f e d c b a From the left: 0 1 2 3 4 5
由於雙端佇列是執行緒安全的,可以在不同的執行緒中同時從兩端利用佇列的內容。
import collections import threading import time candle = collections.deque(xrange(5)) def burn(direction, nextSource): while True: try: next = nextSource() except IndexError: break else: print '%8s: %s' % (direction, next) time.sleep(0.1) print '%8s done' % direction return left = threading.Thread(target=burn, args=('Left', candle.popleft)) right = threading.Thread(target=burn, args=('Right', candle.pop)) left.start() right.start() left.join() right.join()
執行緒交替處理兩端,刪除元素,知道這個deque為空。
Left: 0 Right: 4 Right: 3 Left: 1 Right: 2 Left done Right done
旋轉
deque另外一個作用可以依照任一個方向旋轉,而跳過一些元素。
import collections d = collections.deque(xrange(10)) print 'Normal:', d d= collections.deque(xrange(10)) d.rotate(2) print 'Right roration:', d d = collections.deque(xrange(10)) d.rotate(-2) print 'Left roration:', d
結果:
Normal: deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) Right roration: deque([8, 9, 0, 1, 2, 3, 4, 5, 6, 7]) Left roration: deque([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])
再舉個例子:
# -*- coding: utf-8 -*- """ 下面这个是一个有趣的例子,主要使用了deque的rotate方法来实现了一个无限循环 的加载动画 """ import sys import time from collections import deque fancy_loading = deque('>--------------------') while True: print '\r%s' % ''.join(fancy_loading), fancy_loading.rotate(1) sys.stdout.flush() time.sleep(0.08)
輸出結果:
# 一个无尽循环的跑马灯 ------------->-------