使用队列模块在Python中进行堆栈和排队

在Python中,实现堆栈和队列数据结构非常容易。Stack之所以称为LIFO,是因为Stack遵循“先进先出”的原则,而Queue之所以称为FIFO是因为Queue遵循“先进先出”的原则,而Python中的内置函数使代码更短,更简单。

队列模块实现了多生产者,多消费者队列,当必须在多个线程之间安全地交换信息时,它在线程编程中特别有用。该模块中的Queue类实现了所有必需的锁定语义,并且取决于Python中线程支持的可用性。

该模块实现了三种类型的队列,它们的区别仅在于检索条目的顺序不同。对于FIFO队列,添加的第一个任务是第一个检索到的;对于LIFO队列,最近添加的条目是第一个检索(像堆栈一样操作)。对于优先级队列,条目将保持排序(使用heapq模块),然后首先检索值最低的条目。

此队列模块定义以下类和异常。

Queue.Queue类(maxsize = 0)

这是FIFO队列的构造函数。参数maxsize是一个整数,用于设置可以放入队列中的项目数的上限。一旦达到此大小,插入将被阻塞,直到消耗队列项目为止。如果maxsize小于或等于零,那么队列大小将是无限的。

Queue.LifoQueue类(maxsize = 0)

这是LIFO队列的构造函数。参数maxsize是一个整数,用于设置可以放入队列中的项目数的上限。一旦达到此大小,插入将被阻塞,直到消耗队列项目为止。如果maxsize小于或等于零,那么队列大小将是无限的。

Queue.PriorityQueue(maxsize = 0)类

这是优先级队列的构造函数。参数maxsize是一个整数,用于设置可以放入队列中的项目数的上限。一旦达到此大小,插入将被阻塞,直到消耗队列项目为止。如果maxsize小于或等于零,那么队列大小是无限的。

异常Queue.Empty

此行表示在get()空对象的Queue对象上调用非阻塞(或get_nowait())时引发的异常。

异常Queue.Full

此行表示在put()已满的Queue对象上调用非阻塞(或put_nowait())时引发的异常。

队列对象

Queue.qsize()

此函数返回队列的大概大小。

Queue.empty()

如果队列为空,则此函数返回True,否则返回False。如果empty()返回True,则不保证后续的调用put()不会阻塞。同样,如果empty()返回False,则不能保证后续的调用get()不会阻塞。

Queue.full()

如果队列已满,则返回True,否则返回False。如果full()返回True,则不保证后续的调用get()不会阻塞。同样,如果full()返回False,则不能保证后续的调用put()不会阻塞。

Queue.put(item [,block [,timeout]])

将项目放入队列。如果可选的args块为true,并且超时为None(默认值),则在必要时进行阻塞,直到有可用的插槽为止。如果超时为正数,则在最多超时秒内阻塞,并在该时间内没有可用插槽的情况下引发Full异常。否则(block为false),如果有空闲插槽立即可用,则将项目放入队列中,否则引发Full异常(在这种情况下将忽略超时)。

Queue.get([block [,timeout]])

从队列中删除并返回一个项目。如果可选的args块为true,并且超时为None(默认值),则必要时进行阻塞,直到有可用项为止。如果超时为正数,则它最多会阻塞超时秒,如果在该时间内没有可用的项目,则会引发Empty异常。否则(块为false),如果一项立即可用,则返回一个项目,否则引发Empty异常(在这种情况下将忽略超时)。

Queue.task_done()

表示先前入队的任务已完成。由队列使用者线程使用。对于每个get()用于提取任务的任务,随后对task_done()的调用将告诉队列该任务的处理已完成。

如果ajoin()当前正在阻塞,它将在所有项目都已处理完毕后恢复(这意味着已收到put()队列中的每个项目都收到task_done()调用)。

如果调用的次数超过队列中放置的项目的次数,则引发ValueError。

Queue.join()

阻塞直到队列中的所有项目都已获得并处理。

每当将项目添加到队列时,未完成任务的数量就会增加。每当使用者线程调用task_done()表示已检索到该项目并且该项目的所有工作已完成时,该计数就会减少。当未完成的任务数降至零时,join()取消阻止。

范例程式码

import queue
#maximum capacity of queue is 20
Q = queue.Queue(maxsize=40)
Q.put(50)
Q.put(90)
Q.put(10)
Q.put(70)
print(Q.get())
print(Q.get())
print(Q.get())
print(Q.get())

输出结果

50
90
10
70

下溢/上溢示例

import queue
Q = queue.Queue(maxsize=30)
print(Q.qsize())
Q.put(50)
Q.put(90)
Q.put(10)
Q.put(70)
print("Full: ", Q.full())
Q.put(90)
Q.put(100)
print("Full: ", Q.full())
print(Q.get())
print(Q.get())
print(Q.get())
print("Empty: ", Q.empty())
print(Q.get())
print(Q.get())
print(Q.get())
print("Empty: ", Q.empty())
print("Full: ", Q.full())

输出结果

0
Full: False
Full: False
50
90
10
Empty: False
70
90
100
Empty: True
Full: False

例3

import queue
S = queue.LifoQueue(maxsize=10)
# qsize() give the maxsize of
# the Queue
print(S.qsize())
S.put(50)
S.put(90)
S.put(10)
S.put(70)
S.put(90)
S.put(10)
print("Full: ", S.full())
print("Size: ", S.qsize())
# Data will be accessed in the
# reverse order Reverse of that
# of Queue
print(S.get())
print(S.get())
print(S.get())
print(S.get())
print(S.get())
print("Empty: ", S.empty())

输出结果

0
Full: False
Size: 6
10
90
70
10
90
Empty: False