1. 程式人生 > >[Python] deque (double-ended queue)

[Python] deque (double-ended queue)

參考資料

上面只是非常簡單的介紹了一下collections模組的主要內容,主要目的就是當你碰到適合使用 它們的場所時,能夠記起並使用它們,起到事半功倍的效果。

如果要對它們有一個更全面和深入瞭解的話,還是建議閱讀官方文件和模組原始碼。

Python的collections中有一個deque,這個物件類似於list列表,不過你可以操作它的“兩端”。比如下面的例子:

  1. import collections
  2. d=collections.deque(‘abcdefg’)
  3. print ‘Deque:’,d
  4. print ‘Length:’,len(d)
  5. print ‘Left end:’,d[0
    ]
  6. print ‘Right end:’,d[-1]
  7. d.remove(‘c’)
  8. print ‘remove(c):’,d

下面是輸出的結果,從結果看好像似乎和普通的list沒有多大區別:

  1. Deque: deque([‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’])
  2. Length: 7
  3. Left end: a
  4. Right end: g
  5. remove(c): deque([‘a’, ‘b’, ‘d’, ‘e’, ‘f’, ‘g’])

不過,下面的例子就可以看到,deque是通過extend方法初始化集合元素的,同時你可以通過extendleft將結合元素從“左邊”加入到集合中:

  1. import collections
  2. d1=collections.deque()
  3. d1.extend(‘abcdefg’)
  4. print ‘extend:’,d1
  5. d1.append(‘h’)
  6. print ‘append:’,d1
  7. # add to left
  8. d2=collections.deque()
  9. d2.extendleft(xrange(6))
  10. print ‘extendleft:’,d2
  11. d2.appendleft(6)
  12. print ‘appendleft:’,d2

從輸出的結果,我們可以看到,append預設從集合的右邊增加陣列元素,而另一個appendleft可以從集合的左邊增加元素,輸出結果如下:

  1. extend: deque([‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’])
  2. append: deque([‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’])
  3. extendleft: deque([5, 4, 3, 2, 1, 0])
  4. appendleft: deque([6, 5, 4, 3, 2, 1, 0])

與append和appendleft方法對應的還有pop和popleft方法分別用於從集合中取出元素,看下面的例子:

  1. import collections
  2. print “From the right”
  3. d=collections.deque(‘abcdefg’)
  4. while True:
  5.     try:
  6.         print d.pop(),
  7.     except IndexError:
  8.         break
  9. print
  10. print ‘\n From the left’
  11. d=collections.deque(xrange(6))
  12. while True:
  13.     try:
  14.         print d.popleft(),
  15.     except IndexError:
  16.         break
  17. print

其輸出結果為:

  1. From the right
  2. g f e d c b a
  3.  From the left
  4. 0 1 2 3 4 5

最後值得一提的是,deque是執行緒安全的,也就是說你可以同時從deque集合的左邊和右邊進行操作而不會有影響,看下面的程式碼:

  1. import collections
  2. import threading
  3. import time
  4. candle=collections.deque(xrange(5))
  5. def burn(direction,nextSource):
  6.     while True:
  7.         try:
  8.             next=nextSource()
  9.         except IndexError:
  10.             break
  11.         else:
  12.             print ‘%s : %s’ % (direction,next)
  13.             time.sleep(0.1)
  14.     print “done %s” % direction
  15.     return
  16. left=threading.Thread(target=burn,args=(‘left’,candle.popleft))
  17. right=threading.Thread(target=burn,args=(‘right’,candle.pop))
  18. left.start()
  19. right.start()
  20. left.join()
  21. right.join()

為了試驗執行緒安全,我們分別起了兩個執行緒從deque的左邊和右邊開始移出集合元素,其輸出結果如下:

  1. left : 0
  2. right : 4
  3. right : 3left : 1
  4. left : 2
  5. done right
  6. done left