我的Python程序员

python3.6 queue模块

2018-12-16  本文已影响0人  _AlphaBaby_

python中的queue模块其实是对数据结构中队列这种数据结构的封装,把抽象的数据结构封装成类的属性和方法。这里主要谈下,这些方法。

数据结构基础

栈(stack)也可以说是种先行后出队列(First in Last out),这种数据结构,是先进后出的特点。

打个比方:比如我们把一本一本的书放进一个刚好能容下的桶里面,后放入的书会压着先放入的书。如果我们想要从桶里面取出书籍,那么就只有从后放入的书种先取出来。类似于这种先进后出的模型便是了。

队列(queue)特点是先进先出(First in First out)。

打个比方:我们去食堂排队的时候,总是先去排队的人能够先打到饭,后进入队列排队的人总是后打到饭。这样的数据类型便成为队列。

如果还想学习更多关于数据结构的知识,可以去买本书籍,推荐《大话数据结构》,这本书很浅显易懂的讲解了数据结构的知识。这本书一个大佬也推出了一个配套的教学视频,《小甲鱼数据结构》(上bilibili.com就可以搜索到)。

queue模块中表达队列

在队列中涉及到这样的几个操作:入队(把数据添加到队尾)、出队(从队首取出一个数据)、队列初始化(创建一个队列)、销毁一个队列(把整个队列的数据从内存中删除)、判断队列是否为空判断队列是否满获取队列的长度

python封装好的队列方法

import queue

q = queue.Queue(3)  # 调用构造函数,初始化一个大小为3的队列
print(q.empty())  # 判断队列是否为空,也就是队列中是否有数据
#  入队,在队列尾增加数据, block参数,可以是True和False 意思是如果队列已经满了则阻塞在这里,
# timeout 参数 是指超时时间,如果被阻塞了那最多阻塞的时间,如果时间超过了则报错。
q.put(13, block=True, timeout=5)
print(q.full())  # 判断队列是否满了,这里我们队列初始化的大小为3
print(q.qsize())  # 获取队列当前数据的个数
#  block参数的功能是 如果这个队列为空则阻塞,
#  timeout和上面一样,如果阻塞超过了这个时间就报错,如果想一只等待这就传递None
print(q.get(block=True, timeout=None))

#  queue模块还提供了两个二次封装了的函数,
q.put_nowait(23)  # 相当于q.put(23, block=False)
q.get_nowait()  # 相当于q.get(block=False)

此外,queue模块实现了面向多生产线程、多消费线程的队列。

task_done()
意味着之前入队的一个任务已经完成。由队列的消费者线程调用。每一个get()调用得到一个任务,接下来的task_done()调用告诉队列该任务已经处理完毕。

如果当前一个join()正在阻塞,它将在队列中的所有任务都处理完时恢复执行(即每一个由put()调用入队的任务都有一个对应的task_done()调用)。

join()
阻塞调用线程,直到队列中的所有任务被处理掉。

只要有数据被加入队列,未完成的任务数就会增加。当消费者线程调用task_done()(意味着有消费者取得任务并完成任务),未完成的任务数就会减少。当未完成的任务数降到0,join()解除阻塞。

这两个方法到底怎么用呢?下面我给出两个例子:

import queue

q = queue.Queue(3)
q.put(13, block=True, timeout=5)
q.put_nowait(23)
q.task_done()
print(q.get())
q.join()

这段代码执行完后会一直阻塞着

import queue

q = queue.Queue(3)
q.put(13, block=True, timeout=5)
q.task_done()
q.put_nowait(23)
q.task_done()
print(q.get())
q.join()

这段代码执行后并不会会阻塞着,这是为什么呢?

其实为了实现多线程环境下对队列的支持,当我们调用put的时候可以看做我们给这个队列增加了一个任务,只有到调用task_done()函数是才表示完成了一个任务。而join()函数表示我们所有的任务都完成后才会不被阻塞。

python封装好的栈方法

栈的方法和队列的一模一样,只是有一点不同,我们在调用,put()get()的顺序是不一样的。其他的东西都是和上面队列是一样的。

python封装好的优先队列方法

什么是优先队列
普通的队列其实是:先进后出,或者是先进先出。
但是优先队列就不一样了,它是怎么出的规则不和进入的顺序有关,是和他的优先级有关,当入队的时候我们就会根据这个数据的优先级进行排序,优先级高的就排在前面,然后出队的时候就是先出队。

看这样一个例子:

import queue

q = queue.PriorityQueue(4)
q.put((1,'abcb'))
q.put((1,'abc1'))
q.put((1,'abc3'))
q.put((2,'abc4'))

print(q.get())
print(q.get())
print(q.get())
print(q.get())

这里会根据数据的大小比较进行排序,然后在调用get()时根据优先顺序进行出队列。

python封装好的双向队列方法

可以把双向队列看做是队列和栈的一个升级版。
栈是在一端进行入栈和出站,而队列是在一端入栈一端出栈。
而双向队列则是两端都可以进同时也可以出。

import queue

q = queue.deque(3)  # 初始化一个双向队列
q.append(12)  # 右边进
q.pop()  # 右边出

q.appendleft(34)  # 左边进
q.popleft()  # 左边出

python自己有提供的内存回收机制,所以不需要我们手动销毁队列或者栈

推荐一些好文章

简析Python中的四种队列
每周一个 Python 模块 | Queue
Python Queue 源码解读
Python 多线程|Queue队列|生产者消费者模式|

上一篇 下一篇

猜你喜欢

热点阅读