详解Python中 queue.queue 和 collections.deque 的区别

  • Post category:Python

Python中的queue和collections库中都有队列的实现。queue实现的队列主要用于多线程编程,而collections中的deque实现的队列则用于高性能的单线程情况下的队列操作。

queue库中的queue.Queue是一个线程安全的队列,可以实现多个线程之间的数据共享,其内部实现使用了锁机制来保证线程安全。queue模块提供了3种队列模式:先进先出(FIFO)、后进先出(LIFO)和优先级队列(优先级越高越先出队)。queue.Queue的常用方法包括put()、get()、put_nowait()、get_nowait()、task_done()和join()。

示例1:实现多线程获取网页数据并存入队列中

import threading
import queue

def download_webpage(queue):
    for url in ["url1", "url2", "url3"]:
        data = "<html>data for %s</html>" % url
        queue.put(data)

def parse_webpage(queue):
    while True:
        data = queue.get()
        # 解析数据
        queue.task_done()

q = queue.Queue()
t1 = threading.Thread(target=download_webpage, args=(q,))
t2 = threading.Thread(target=parse_webpage, args=(q,))
t1.start()
t2.start()
t1.join()
t2.join()

collections中的deque是一个双端队列,可以在队列的两端进行插入和删除操作,deque是线程不安全的,因此在多线程环境中需要自行使用锁来保证线程安全。deque支持与list相同的操作,包括append()、appendleft()、pop()、popleft()、extend()、extendleft()等。

示例2:使用deque实现贪吃蛇游戏

from collections import deque
import random

# 初始化蛇头和蛇身位置
snake = deque([(0, 0)])
# 初始化蛇的长度
snake_len = 1

# 随机生成食物位置
food = (random.randint(0, 4), random.randint(0, 4))

# 移动蛇的位置
def move_snake(direction):
    # 计算蛇头新位置
    head = snake[-1]
    if direction == "up":
        new_head = (head[0] - 1, head[1])
    elif direction == "down":
        new_head = (head[0] + 1, head[1])
    elif direction == "left":
        new_head = (head[0], head[1] - 1)
    elif direction == "right":
        new_head = (head[0], head[1] + 1)
    # 判断蛇头新位置是否合法
    if new_head[0] < 0 or new_head[0] > 4 or new_head[1] < 0 or new_head[1] > 4:
        return False
    # 判断蛇头新位置是否与蛇身重合
    if new_head in snake:
        return False
    # 完成移动
    snake.append(new_head)
    # 判断是否吃到食物
    if new_head == food:
        global snake_len, food
        snake_len += 1
        food = (random.randint(0, 4), random.randint(0, 4))
    else:
        snake.popleft()
    return True