Python 队列queue和集合collections的区别
队列是一种遵循FIFO(先进先出)传递方法的数据结构,即一组消息的顺序严格保留。它仅处理所有消息一次,因此没有消息的重复。
先进先出系统相对于标准传递方法的优势在于队列支持无限吞吐量,因为它应用了队列的批处理。FIFO具有高吞吐量(通过过程传递的项的数量)并且可以处理比平均值更多的消息。
在Python中,可以通过两个主要的库,collections和queue库,来实现队列。虽然它们都用于队列实现,但两者之间有许多不同之处,可以在不同的用例场景中进行优化。主要的区别如下:
主要区别
类别 | queue.Queue() | collections.deque() |
---|---|---|
同步操作 | ‘queue.Queue’通过实现同步操作,提供了安全的多线程操作处理。 | ‘collections.deque’默认情况下不是同步的,因此对于可能使用多个线程的操作可能不适用。 |
功能 | ‘queue.Queue’专用于队列的实现,采用先进先出的投递系统,元素从末尾添加。它提供了put()和get()等函数,用于向队列中的元素进行入队和出队操作。 | 对于’collections.deque’而言,它更多地是一种标准实现,同时实现了后进先出和先进先出的概念,因此也可以用于栈操作。通过append()、pop()和popleft()等函数,您可以在双端队列中添加和删除元素。 |
杂项 | ‘queue.Queue’除了基本的队列功能外,并没有提供太多其他功能。 | ‘collections.deque’提供了更多的功能,可以使用像rotate()将队列以任意方式旋转,以及使用remove()来删除特定元素的函数来修改或更改给定队列。 |
性能 | 就复杂度而言,’collections.deque’由于使用了双向链表,因此更快。由于这个原因,它的复杂度为O(1),可以执行更快的操作。 | 在’queue.Queue’中,由于同步的开销,特别是在多线程进程中,速度稍慢一些。 |
queue.Queue
在Python中,queue模块提供了一个’Queue()’类,它提供了一种数据结构。Queue()类具有通过实现队列数据结构的队列方法。
语法
Queue().put(value)
Queue().get(value)
在这里,value是使用put()函数入队列的元素。要从队列中删除元素,我们使用get()函数进行出队列操作。
步骤
- 导入库。
-
初始化队列。
-
将一些元素入队列。
-
检查它们是否为空。
-
如果不为空,则出队列元素并打印它们。
示例
#import the necessary library
from queue import Queue
#assign an object to the queue class
m_q=Queue()
#Enqueue elements in a queue
m_q.put(20)
m_q.put(40)
m_q.put(60)
#Dequeuing the elements and printing them
while not m_q.empty():
i=m_q.get()
print(i)
输出
20
40
60
我们首先导入队列模块并为队列类分配一个对象。然后,我们使用put()函数将元素入队。然后,我们初始化一个while循环,以便在队列为空之前一直出队元素。然后,出队的元素将作为输出打印出来。
collections.deque
在Python中,使用collections.deque类引入双向队列数据结构。”Deque”代表”double-ended queue”。在这种数据结构中,可以高效地从队列的两端添加或移除元素。
语法
deque().append(20)
deque().appendleft(60)
deque().pop()
deque().popleft()
在这里我们使用deque(双向队列)展示了在deque的两侧进行入队和出队操作。
20被正常地添加,然后60被添加到20的左侧。之后,可以使用pop()和popleft()函数对任一侧进行出队操作。
步骤
- 导入库。
-
初始化deque。
-
从左侧或右侧添加元素。
-
弹出元素。
-
打印队列。
示例
from collections import deque
# Create a new deque
my_deque = deque()
# Add elements to the deque
my_deque.append(20) # Add to the right end
my_deque.appendleft(40) # Add to the left end
my_deque.append(60) #Add to right end
print("Initial deque: \n",my_deque)
# Remove elements from the deque
right_element = my_deque.pop() # Remove from the right end
print("\nAfter removing element from right: \n",my_deque)
left_element = my_deque.popleft() # Remove from the left end
print("\nAfter removing element from left :\n", my_deque)
# Print the deque's contents
my_deque.pop()
print("\nFinal deque: \n",my_deque)
输出
Initial deque:
deque([40, 20, 60])
After removing element from right:
deque([40, 20])
After removing element from left :
deque([20])
Final deque:
deque([])
它的一些优点是
简化复杂度 | collections.deque()’由于使用了双向链表,具有较低的复杂度,并且具有O(1)的复杂度,适用于队列的两端进行插入和删除操作的场景。 |
---|---|
动态大小 | 与常规队列不同,其中容量是事先定义好的,存储非常严格,collections.deque可以动态改变队列的大小。在达到最大容量时,无需调整大小或复制元素。 |
结论
‘queue.Queue’ 和 ‘collections.deque’ 都用于队列的实现。但是,从性能上来看,在执行不同的操作时它们提供了非常微小的差异。但是,由于具有额外的功能,’collections.deque’ 被广泛使用。除了在多线程示例中关键的同步情况下,大多数情况下都使用 ‘collections.deque’。