Deque is the abbreviation of double-ended queue, similar to list, but provides insertion and deletion operations at both ends.
For example:
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'])
As a double-ended queue, deque also provides some other useful methods, such as rotate, etc. Let’s take a look at them below:
Padding
Deque can be filled from either end, which is called "left end" and "right end" in 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() iteratively processes its input, completing the same processing as appendleft() for each element.
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])
Use
Deque elements can be utilized from both ends, depending on the algorithm applied.
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
Use pop() to delete an element from the right end of deque, and use popleft() to delete an element from the left end of deque.
From the right: g f e d c b a From the left: 0 1 2 3 4 5
Since deques are thread-safe, the contents of the queue can be utilized from both ends simultaneously in different threads.
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()
The thread processes both ends alternately, deleting elements until the deque is empty.
Left: 0 Right: 4 Right: 3 Left: 1 Right: 2 Left done Right done
Rotate
Another function of deque is that it can rotate in any direction and skip some elements.
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
Result:
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])
Another example:
# -*- 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)
Output result:
# 一个无尽循环的跑马灯 ------------->-------