I used to want to find the average of Queue values (I don't remember why I needed it). At that time, I used the following code to find the average value.
queue_test.py
import queue
def queue_ave(q):
queue_list = []
while not q.empty():
queue_list.append(q.get())
for value in queue_list: #reversed for stack(queue_list)change to
q.put(value)
return sum(queue_list) / len(queue_list)
#Operation check
q = queue.Queue()
q.put(1)
q.put(2)
q.put(6)
q.put(8)
print(queue_ave(q)) # 4.25
The flow of this code (function) is
It is something like. Certainly, the average value of Queue can still be calculated. However, as a matter of course, it is very inefficient because it costs a lot of calculation because it repeats put and get in vain.
Therefore, another approach is to inherit the Queue class from the standard library queue and create a customized class.
To do this, check how the Queue class manages the values. I think it depends on the editor, but you can see the source code by "Ctrl + click" the class you want to check.
queue.py
class Queue:
'''Create a queue object with a given maximum size.
If maxsize is <= 0, the queue size is infinite.
'''
#~ Omitted ~
def put(self, item, block=True, timeout=None):
'''Put an item into the queue.
If optional args 'block' is true and 'timeout' is None (the default),
block if necessary until a free slot is available. If 'timeout' is
a non-negative number, it blocks at most 'timeout' seconds and raises
the Full exception if no free slot was available within that time.
Otherwise ('block' is false), put an item on the queue if a free slot
is immediately available, else raise the Full exception ('timeout'
is ignored in that case).
'''
with self.not_full:
if self.maxsize > 0:
if not block:
if self._qsize() >= self.maxsize:
raise Full
elif timeout is None:
while self._qsize() >= self.maxsize:
self.not_full.wait()
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
endtime = time() + timeout
while self._qsize() >= self.maxsize:
remaining = endtime - time()
if remaining <= 0.0:
raise Full
self.not_full.wait(remaining)
self._put(item)
self.unfinished_tasks += 1
self.not_empty.notify()
If you look at the put method, it says various things, but it seems that the \ _put method is used to store the value. Now let's look at the \ _put method and so on.
queue.py
from collections import deque
class Queue:
#~ Omitted ~
# Put a new item in the queue
def _put(self, item):
self.queue.append(item)
# Initialize the queue representation
def _init(self, maxsize):
self.queue = deque()
From the \ _put method, I found that the value is stored in self.queue. In addition, the \ _init method used during initialization tells us that self.queue is a deque instance.
In other words, the Queue class seems to use the deque class of collections to manage the values. I won't go into this here, but the deque class seems to be treated like an array (probably).
With these things in mind, inherit the Queue class and customize it to your liking.
queue_test.py
import queue
class MyQueue(queue.Queue):
def show_value(self, i):
print(self.queue[i])
def sum(self):
return sum(self.queue)
def ave(self):
return self.sum() / self.qsize()
#Operation check
q = MyQueue()
q.put(1)
q.put(2)
q.put(6)
q.put(8)
q.show_value(2) # 6
print(q.sum()) # 17
print(q.ave()) # 4.25
Now you have created a new MyQueue class that inherits from the Queue class and expanded its functionality. The cost is low because there is no unnecessary operation, and above all, the code is clean. At this level, if you try to do something more complicated, it will make a big difference.
This time, I inherited the existing library queue.Queue and customized it to my liking.
It is also important to have the ability to push and solve what you can do now. However, if you have the time and the solution, it is smart to choose a simpler method. The code will be cleaner and will be good for the future.
Recommended Posts