python--队列模块(自带)

文章目录

      • 1. FIFO(Queue) -- 先进先出
      • 2. LIFO(LifoQueue) -- 后进先出
      • 3. priority(PriorityQueue) -- 优先队列
      • 4. deque -- 双端队列

Python自带的队列模块有4种队列:

  • FIFO(Queue): first in first out 先进先出
  • LIFO(LifoQueue): last in first out 后进先出,类似于栈的数据结构
  • priority(PriorityQueue): 优先队列
  • deque: 双端队列

1. FIFO(Queue) – 先进先出

  • 导入模块
from queue import Queue
  • 设置队列长度、进队列与出队列
from queue import Queue

if __name__ == "__main__":
    # 如果maxsize设置为小于0或者不设置,队列为无限长
    que = Queue(maxsize=2)
    # 进队列
    que.put(1)
    # 出队列
    result = que.get()
    print(result)

>>>>>>
1
  • 入队列时堵塞
from queue import Queue

if __name__ == "__main__":
    que = Queue(maxsize=1)
	# 此时如果入队列两次, put将会一直堵塞,等待前一个出队列
    que.put(1)
    que.put(2)
    print("ok")
  • 入队列非堵塞.
from queue import Queue

if __name__ == "__main__":
    que = Queue(maxsize=1)
    que.put(1)
    try:
        # 如果队列为满,非堵塞将会报异常
        que.put(2, block=False)
    except Exception:
        print("队列已满")

>>>>>>
队列已满
  • 出队列堵塞
from queue import Queue

if __name__ == "__main__":
    que = Queue(maxsize=2)
    que.put(1)
    que.get()
    que.get()
    print("ok")
    # 如果队列为空,get会一直等待
  • 出队列非堵塞
from queue import Queue

if __name__ == "__main__":
    que = Queue(maxsize=2)
    que.put(1)
    que.get()
    try:
        # 如果队列为空,非堵塞将会报异常
        que.get(block=False)
    except Exception:
        print("队列已空")

>>>>>>
队列已空
  • 设置超时
from queue import Queue

if __name__ == "__main__":
    que = Queue(maxsize=1)
    que.put(1)
    try:
        # 设置超时后,如果2秒后还不能进队列将会报异常
        # 在非堵塞的情况下,无需设置超时
        que.put(2, timeout=2)
    except Exception:
        print("队列已满")
    
    que.get()
    try:
        # 设置超时后,如果2秒后队列仍是空将会报异常
        # 在非堵塞的情况下,无需设置超时
        que.get(2, timeout=2)
    except Exception:
        print("队列已空")

>>>>>>
队列已满
队列已空
  • join( )与task_done( )的关系
    在多线程中,队列设置join后,将会一直等待队列为空才会结束,而task_done就是告诉join何时结束,但是如果队列仍有数据,就算写了task_done程序依然会一直堵塞,这是一个对队列的保护措施。
from queue import Queue
from threading import Thread
import time

que = Queue()

def task(value):
    global que
    que.put(value)
    # que.put(value)

def task2():
    global que
    res = que.get()
    print(res)
    que.task_done()

if __name__ == "__main__":
    t1 = Thread(target=task, args=(10,))
    t2 = Thread(target=task2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    que.join()

>>>>>>
10

队列常用方法:

  • que.put_nowait(): 相当于put(item,block=False)
  • que.get_nowait(): 相当于get(block=False)
  • que.empty(): 判断队列是否为空,如果为空返回True,反之返回False
  • que.full(): 判断队列是否为满,如果为满返回True,反之返回False
  • que.qsize(): 返回当前队列有多少成员
  • que.maxsize: 返回队列的最大长度

2. LIFO(LifoQueue) – 后进先出

  • 导入模块
from queue import LifoQueue
  • 查看源码会发现LifoQueue是继承了Queue队列,所以使用创建对象时用法跟Queue一样
from queue import LifoQueue

if __name__ == "__main__":
    lq = LifoQueue(maxsize=2)
    lq.put(20)
    lq.put(10)
    print(lq.get())
    print(lq.get())

>>>>>>
10
20
  • LIFO和FIFO的队列唯一的不同就是进队列与出队列的方式,其他用法一致。

3. priority(PriorityQueue) – 优先队列

  • 导入模块
from queue import PriorityQueue
  • 查看源码会发现PriorityQueue是继承了Queue队列,所以使用创建对象时用法跟Queue一样
from queue import PriorityQueue

if __name__ == "__main__":
    pq = PriorityQueue()
    pq.put(20)
    pq.put(10)
    pq.put(30)
    print(pq.get())
    print(pq.get())
    print(pq.get())

>>>>>>
10
20
30

优先队列的出队列是按照从小到大的,如何定义优先级
PriorityQueue源码:

Variant of Queue that retrieves open entries in priority order (lowest first).
Entries are typically tuples of the form: (priority number, data).

  • 优先级是根据元组的(优先级号,数据),可以通过元组的方式,设置数据的优先级
from queue import PriorityQueue

if __name__ == "__main__":
    pq = PriorityQueue()
    pq.put((1, 20))
    pq.put((3, 10))
    pq.put((2, 30))
    print(pq.get()[1])
    print(pq.get()[1])
    print(pq.get()[1])

>>>>>>
20
30
10

4. deque – 双端队列

  • 导入模块
from collections import deque
  • 初始化队列
dq = deque([可迭代对象][队列长度])
  • 此队列可以使用任何列表的操作,只要列表可以的操作,此队列都可以使用
from collections import deque

if __name__ == "__main__":
    dq = deque(["a", "b", "d", "c", "e"])
    print(dq.pop())  # 右弹出 >>> e
    print(dq.popleft())  # 左弹出 >>> a

    dq.append(1)  # 右添加
    dq.appendleft(2)  # 左添加
    print(dq)  # >>> deque([2, 'b', 'd', 'c', 1])

    dq.insert(3, "haha")  # 指定位置插入数据
    print(dq)  # >>> deque([2, 'b', 'd', 'haha', 'c', 1])

    # 可迭代对象入队
    dq.extend(['D', 'E'])  # 右入队
    dq.extendleft(['A', 'B'])  # 左入队
    print(dq)  # >>> deque(['B', 'A', 2, 'b', 'd', 'haha', 'c', 1, 'D', 'E'])

    # 翻转
    dq.reverse()
    print(dq)  # >>> deque(['E', 'D', 1, 'c', 'haha', 'd', 'b', 2, 'A', 'B'])
    # 轮转:每次轮转是将队尾的数据出队然后从队头入队,相当于先pop()再appendleft(item),retate(num)中传入轮转的次数
    dq.rotate(3)
    print(dq)  # >>> deque([2, 'A', 'B', 'E', 'D', 1, 'c', 'haha', 'd', 'b'])
    # 复制
    dq_2 = dq.copy()
    print(id(dq))  # >>> 140463460679488
    print(id(dq_2))  # >>> 140463459369792

    # deque指定队列的长度
    dq = deque(maxlen=5)
    dq.extend([1, 2, 3, 4, 5])
    print(dq)  # >>> deque([1, 2, 3, 4, 5], maxlen=5)
    dq.append('F')
    print(dq)  # >>> deque([2, 3, 4, 5, 'F'], maxlen=5)
    dq.appendleft('A')
    print(dq)  # >>> deque(['A', 2, 3, 4, 5], maxlen=5)

你可能感兴趣的:(python,队列)