Check whether a given element is inside queue - python

I created a queue and i need to check whether a given element is inside that queue or not and to run the program according to that! Following is my code and it doesn't do what i want and it gives as "duplicate" for all inputs! Please help!
def Arrival(vehicle):
if vehicle in q1.items:
print "duplicate!"
else:
if q1.size()<10:
if q3.isEmpty()==False:
EnterOld=q3.dequeue()
q1.enqueue(EnterOld)
print "The car number "+str(EnterOld)+" can enter now from the waiting line!"
else:
print"the car number "+str(vehicle)+" can enter the park!"

The problem is in your if statement.
if vehicle in q1.items or q3.items:
What this does is check 'is vehicle an element of q1.items', if not it checks 'is q3.items' True when evaluated as a boolean?
You should do:
if vehicle in q1.items or vehicle in q3.items:

I understand that the vehicle is duplicate if it is in both q1 and q3, so this should be
if vehicle in q1.items and vehicle in q3.items:

class queue:
def __init__(self):
self.items = []
def __iter__(self):
for i in self.items:
yield i
def isEmpty(self):
return self.items == []
def enqueue(self,item):
self.items.insert(0,item)
def dequeue(self):
return self.items.pop()
def size(self):
return len(self.items)
def front(self):
return self.items[len(self.items)-1]
def index(self,item):
return self.items.index(item)

This is my code. Hopefully, it can help someone.
I added set as a cache to the Queue class. This cache was utilized for task uniqueness checking. Moreover, it was used to implement the __contains__ magic method in the Queue class.
Uniqueness can be defined in two ways. First, tasks are unique in the whole life of the queue. In other words, the queue rejects accepting a repeated task even after the task is done and removed from the queue. I implemented this as "be_unique_in_all_items". Second, tasks are unique only in the existing tasks in the queue. It means the task can be accepted after it is done. I implemented this as "be_unique_in_existing_items".
from queue import Queue
from traceback import print_exc
class MQueue(Queue):
def __init__(self,
**kwargs):
super().__init__(maxsize=kwargs.get("maxsize", 0))
self._be_unique_in_existing_items = kwargs.get("be_unique_in_existing_items", False)
self._be_unique_in_all_items = kwargs.get("be_unique_in_all_items", False)
if self._be_unique_in_existing_items and self._be_unique_in_all_items:
raise ValueError("Choose one criteria")
self.cache = set()
def get(self, *args, **kwargs):
result = super().get(*args, **kwargs)
if result:
if self._be_unique_in_existing_items:
self.cache.remove(result)
return result
def put(self, item, *args, **kwargs):
if self._be_unique_in_existing_items or self._be_unique_in_all_items:
if item in self.cache:
raise ValueError("The given item exists in cache.")
self.cache.add(item)
return super().put(item, *args, **kwargs)
def __contains__(self, item):
if self._be_unique_in_existing_items or self._be_unique_in_all_items:
return self.cache.__contains__(item)
else:
return Queue.__contains__(item) # will raise you error
if __name__ == "__main__":
# ordinary queue
ordinary_queue_obj = MQueue(maxsize=0)
ordinary_queue_obj.put(1)
ordinary_queue_obj.put(1)
try:
print(1 in ordinary_queue_obj)
except Exception:
print_exc()
# be unique in existing queue
unique_in_existing_queue_obj = MQueue(maxsize=0,
be_unique_in_existing_items=True)
unique_in_existing_queue_obj.put(1)
print(1 in unique_in_existing_queue_obj)
try:
unique_in_existing_queue_obj.put(1)
except ValueError:
print_exc()
task = unique_in_existing_queue_obj.get()
unique_in_existing_queue_obj.task_done()
unique_in_existing_queue_obj.put(task)
# be unique in all queue
unique_in_all_queue_obj = MQueue(maxsize=0,
be_unique_in_all_items=True)
unique_in_all_queue_obj.put(1)
print(1 in unique_in_all_queue_obj)
try:
unique_in_all_queue_obj.put(1)
except ValueError:
print_exc()
task = unique_in_all_queue_obj.get()
unique_in_all_queue_obj.task_done()
try:
print(task in unique_in_all_queue_obj)
unique_in_all_queue_obj.put(task)
except ValueError:
print_exc()
Note: set only can contain hashable objects. For unhashable objects use list instead.

Related

How to make a polymorphic dataclass constructor method

I have 3 dataclass objects say:
class Message1:
def __init__(a):
...
class Message2:
def __init__(d,e,f):
...
class Message3:
def __init__(g,i):
...
For these 3 messages I want to make a factory type method which can return one of the three objects if it succeeds and if not it should return either the one it identified as the correct message to be created but failed at creation or it should notify the user that it could not create any of the messages. Are there any OOP patterns for this?
My initial thought was to do a:
def factory_method(**parameters):
try:
Message1(**parameters)
except TypeError:
try:
Message2(**parameters)
except:
try:
Message3(**parameters)
except:
print("Could not deduce message type")
My issue with this idea is that:
It's not a dynamically scalable solution, with each new message class I introduce I need to add a new try catch block
If the whole nested block structure fails, I have no feedback as to why, was the parameters correct for one of the message but wrong value, or was it plain gibberish?
I realize this might be a bit opinion based on what the best outcome is. At the same time it might be the solution is not too elegant and the simplest way is to just tell the factory_method what kind of message to initialize. Any suggestions or ideas would be appreciated.
If you can't join them all in a single class and you can't point a call to a single class, i would match the arguments to the posible class. To make it work a type hint and a "proxy" class is required. This example asumes that any of the classes wont contain a __init__(*args, **kwargs), and to add a new class you just add it to Message.msg_cls, you can eval the global scope if you don't want to add manually each class.
class Message1:
def __init__(self, a: int, alt=None, num=10):
print('Message 1')
class Message2:
def __init__(self, d: str, e: str, f: int):
print('Message 2')
class Message3:
def __init__(self, g: int, i: any):
print('Message 3')
class Message:
msg_cls = (
Message1,
Message2,
Message3
)
#staticmethod
def eq_kwargs(cls, kwargs):
cls_kwargs = cls.__init__.__defaults__
if cls_kwargs is None:
if len(kwargs) > 0:
return False
else:
return True
cls_astr = cls.__init__.__code__
kw_types = [type(t) for t in cls_kwargs]
for k in kwargs:
if k in cls_astr.co_varnames:
if type(kwargs[k]) in kw_types:
kw_types.remove(type(kwargs[k]))
else:
if type(None) in kw_types:
kw_types.remove(type(None))
else:
return False
else:
return False
return True
#staticmethod
def eq_args(cls, args):
cls_args = cls.__init__.__annotations__
if len(cls_args) != len(args):
return False
for a, b in zip(args, cls_args):
if type(a) != cls_args[b] and cls_args[b] != any:
return False
return True
def __new__(cls, *args, **kwargs):
for mc in Message.msg_cls:
if Message.eq_args(mc, args):
if Message.eq_kwargs(mc, kwargs):
return mc(*args, **kwargs)
raise ValueError('Message.__new__, no match')
if __name__ == '__main__':
ms_1_a = Message(1, alt='a')
ms_1_b = Message(2, alt='a', num=5)
ms_2 = Message('X', 'Y', 5)
ms_3_a = Message(1, [1, 4])
ms_3_b = Message(2, Message(10))

Function does not return expected instance

I have a very specific problem in my code and I just can't figure it out why.
select_desire_tool() returns None.
It seems that when it arrives at return self._associated_instance(value), somehow it finishes some process in the else statement of the for loop and the supposed returned instance is lost.
why is that?
Return specific instance
def _associated_instance(self, argument):
if RegionConstants.SETTINGS == argument:
return Settings()
else:
test.fail("No such instance found.")
raise
## Clicks on desired map tools option
# #param[in] self The self object pointer.
# #param[in] value Map tools option to be selected
# #return specific class instance class instance
def select_desire_tool(self, value):
items_from_list = self.items
for item in items_from_list:
if item.name == value:
while True:
try:
item.click_button()
return self._associated_instance(value)
except LookupError:
Base().Scrollbar().scroll_down()
else:
if not Base().Scrollbar().at_y_end:
Base().Scrollbar().scroll_down()
self.select_desire_tool(value)
else:
test.fail("Option was not found in map tools")
raise

How to eliminate recursion in Python function containing control flow

I have a function of the form:
def my_func(my_list):
for i, thing in enumerate(my_list):
my_val = another_func(thing)
if i == 0:
# do some stuff
else:
if my_val == something:
return my_func(my_list[:-1])
# do some other stuff
The recursive part is getting called enough that I am getting a RecursionError, so I am trying to replace it with a while loop as explained here, but I can't work out how to reconcile this with the control flow statements in the function. Any help would be gratefully received!
There may be a good exact answer, but the most general (or maybe quick-and-dirty) way to switch from recursion to iteration is to manage the stack yourself. Just do manually what programming language does implicitly and have your own unlimited stack.
In this particular case there is tail recursion. You see, my_func recursive call result is not used by the caller in any way, it is immediately returned. What happens in the end is that the deepest recursive call's result bubbles up and is being returned as it is. This is what makes #outoftime's solution possible. We are only interested in into-recursion pass, as the return-from-recursion pass is trivial. So the into-recursion pass is replaced with iterations.
def my_func(my_list):
run = True
while run:
for i, thing in enumerate(my_list):
my_val = another_func(thing)
if i == 0:
# do some stuff
else:
if my_val == something:
my_list = my_list[:-1]
break
# do some other stuff
This is an iterative method.
Decorator
class TailCall(object):
def __init__(self, __function__):
self.__function__ = __function__
self.args = None
self.kwargs = None
self.has_params = False
def __call__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.has_params = True
return self
def __handle__(self):
if not self.has_params:
raise TypeError
if type(self.__function__) is TailCaller:
return self.__function__.call(*self.args, **self.kwargs)
return self.__function__(*self.args, **self.kwargs)
class TailCaller(object):
def __init__(self, call):
self.call = call
def __call__(self, *args, **kwargs):
ret = self.call(*args, **kwargs)
while type(ret) is TailCall:
ret = ret.__handle__()
return ret
#TailCaller
def factorial(n, prev=1):
if n < 2:
return prev
return TailCall(factorial)(n-1, n * prev)
To use this decorator simply wrap your function with #TailCaller decorator and return TailCall instance initialized with required params.
I'd like to say thank you for inspiration to #o2genum and to Kyle Miller who wrote an excellent article about this problem.
Despite how good is to remove this limitation, probably, you have to be
aware of why this feature is not officially supported.

'Queue' object has no attribute 'size'

I have seen other examples of this happening on StackOverflow, but I didn't understand any of the answers (I'm still a new programmer,) nor did the other examples I saw look quite like mine, else I wouldn't post this question.
I'm running Python 3.2 on Windows 7.
I have never had this happen to me before and I've done classes this way many times, so I don't really know what is different this time. The only difference is that I didn't make all of the Class file; I was given a template to fill in and a test file to try it on. It worked on the test file, but is not working on my file. I have been calling on the methods in the class in the exact same way as the test file (e.g. Lineup.size())
This is my Class:
class Queue:
# Constructor, which creates a new empty queue:
def __init__(self):
self.__items = []
# Adds a new item to the back of the queue, and returns nothing:
def queue(self, item):
self.__items.insert(0,item)
return
# Removes and returns the front-most item in the queue.
# Returns nothing if the queue is empty.
def dequeue(self):
if len(self.__items) == 0:
return None
else:
return self.__items.pop()
# Returns the front-most item in the queue, and DOES NOT change the queue.
def peek(self):
if len(self.__items) == 0:
return None
else:
return self.__items[(len(self.__items)-1)]
# Returns True if the queue is empty, and False otherwise:
def is_empty(self):
return len(self.__items) == 0
# Returns the number of items in the queue:
def size(self):
return len(self.__items)
# Removes all items from the queue, and sets the size to 0:
def clear(self):
del self.__items[0:len(self.__items)]
return
# Returns a string representation of the queue:
def __str__(self):
return "".join(str(i) for i in self.__items)
This is my program:
from queue import Queue
Lineup = Queue()
while True:
decision = str(input("Add, Serve, or Exit: ")).lower()
if decision == "add":
if Lineup.size() == 3:
print("There cannot be more than three people in line.")
continue
else:
person = str(input("Enter the name of the person to add: "))
Lineup.queue(person)
continue
elif decision == "serve":
if Lineup.is_empty() == True:
print("The lineup is already empty.")
continue
else:
print("%s has been served."%Lineup.peek())
Lineup.dequeue()
continue
elif (decision == "exit") or (decision == "quit"):
break
else:
print("%s is not a valid command.")
continue
And this is my error message when I enter "add" as my decision variable:
line 8, in
builtins.AttributeError: 'Queue' object has no attribute 'size'
So, what is going on here? What is different about this one?
Python 3 already has a queue module (which you might want to take a look at). When you import queue, Python finds that queue.py file before it finds your queue.py.
Rename your queue.py file to my_queue.py, change your import statements to from my_queue import Queue, and your code will work as you intend.
try rename size for other name or implement a counter to the list __items some like
def get_size(self):
cnt = 0
for i in self.__items:
cnt++
return cnt

How can I make a unique value priority queue in Python?

Python has Queue.PriorityQueue, but I cannot see a way to make each value in it unique as there is no method for checking if a value already exists (like find(name) or similar). Moreover, PriorityQueue needs the priority to remain within the value, so I could not even search for my value, as I would also have to know the priority. You would use (0.5, myvalue) as value in PriorityQueue and then it would be sorted by the first element of the tuple.
The collections.deque class on the other hand does offer a function for checking if a value already exists and is even more natural in usage (without locking, but still atomic), but it does not offer a way to sort by priority.
There are some other implementations on stackoverflow with heapq, but heapq also uses priority within the value (e.g. at the first position of a tuple), so it seems not be great for comparison of already existing values.
Creating a python priority Queue
https://stackoverflow.com/questions/3306179/priority-queue-problem-in-python
What is the best way of creating a atomic priority queue (=can be used from multiple threads) with unique values?
Example what I’d like to add:
Priority: 0.2, Value: value1
Priority: 0.3, Value: value2
Priority: 0.1, Value: value3 (shall be retrieved first automatically)
Priority: 0.4, Value: value1 (shall not be added again, even though it has different priority)
You could combine a priority queue with a set:
import heapq
class PrioritySet(object):
def __init__(self):
self.heap = []
self.set = set()
def add(self, d, pri):
if not d in self.set:
heapq.heappush(self.heap, (pri, d))
self.set.add(d)
def pop(self):
pri, d = heapq.heappop(self.heap)
self.set.remove(d)
return d
This uses the priority queue specified in one of your linked questions. I don't know if this is what you want, but it's rather easy to add a set to any kind of queue this way.
Well here's one way to do it. I basically started from how they defined PriorityQueue in Queue.py and added a set into it to keep track of unique keys:
from Queue import PriorityQueue
import heapq
class UniquePriorityQueue(PriorityQueue):
def _init(self, maxsize):
# print 'init'
PriorityQueue._init(self, maxsize)
self.values = set()
def _put(self, item, heappush=heapq.heappush):
# print 'put',item
if item[1] not in self.values:
print 'uniq',item[1]
self.values.add(item[1])
PriorityQueue._put(self, item, heappush)
else:
print 'dupe',item[1]
def _get(self, heappop=heapq.heappop):
# print 'get'
item = PriorityQueue._get(self, heappop)
# print 'got',item
self.values.remove(item[1])
return item
if __name__=='__main__':
u = UniquePriorityQueue()
u.put((0.2, 'foo'))
u.put((0.3, 'bar'))
u.put((0.1, 'baz'))
u.put((0.4, 'foo'))
while not u.empty():
item = u.get_nowait()
print item
Boaz Yaniv beat me to the punch by a few minutes, but I figured I'd post mine too as it supports the full interface of PriorityQueue. I left some print statements uncommented, but commented out the ones I put in while debugging it. ;)
In case you want to prioritise a task later.
u = UniquePriorityQueue()
u.put((0.2, 'foo'))
u.put((0.3, 'bar'))
u.put((0.1, 'baz'))
u.put((0.4, 'foo'))
# Now `foo`'s priority is increased.
u.put((0.05, 'foo'))
Here is another implementation follows the official guide:
import heapq
import Queue
class UniquePriorityQueue(Queue.Queue):
"""
- https://github.com/python/cpython/blob/2.7/Lib/Queue.py
- https://docs.python.org/3/library/heapq.html
"""
def _init(self, maxsize):
self.queue = []
self.REMOVED = object()
self.entry_finder = {}
def _put(self, item, heappush=heapq.heappush):
item = list(item)
priority, task = item
if task in self.entry_finder:
previous_item = self.entry_finder[task]
previous_priority, _ = previous_item
if priority < previous_priority:
# Remove previous item.
previous_item[-1] = self.REMOVED
self.entry_finder[task] = item
heappush(self.queue, item)
else:
# Do not add new item.
pass
else:
self.entry_finder[task] = item
heappush(self.queue, item)
def _qsize(self, len=len):
return len(self.entry_finder)
def _get(self, heappop=heapq.heappop):
"""
The base makes sure this shouldn't be called if `_qsize` is 0.
"""
while self.queue:
item = heappop(self.queue)
_, task = item
if task is not self.REMOVED:
del self.entry_finder[task]
return item
raise KeyError('It should never happen: pop from an empty priority queue')
I like #Jonny Gaines Jr.'s answer but I think it can be simplified. PriorityQueue uses a list undert he hood, so you can just define:
class PrioritySetQueue(PriorityQueue):
def _put(self, item):
if item not in self.queue:
super(PrioritySetQueue, self)._put(item)

Categories

Resources