Confused about the size() function in python - python

I'm going through the code to write a circular queue in python
class CircularQueue:
# constructor for the class
# taking input for the size of the Circular queue
# from user
def __init__(self, maxSize):
self.queue = list()
# user input value for maxSize
self.maxSize = maxSize
self.head = 0
self.tail = 0
# add element to the queue
def enqueue(self, data):
# if queue is full
if self.size() == (self.maxSize - 1):
return("Queue is full!")
else:
# add element to the queue
self.queue.append(data)
# increment the tail pointer
self.tail = (self.tail+1) % self.maxSize
return True
and the part that confuses me is the self.size() in the method "enqueue"
I looked through the python docs and don't see any size() function, only references to size() in numpy.
Normally you'd want to call len() for the size of a list, but I know you can't do self.len()
any clarity/explanation of the syntax and logic behind writing something like this would be helpful!

You need to define your own size() method and just return the number of items currently held in the queue.

Related

Multiprocessing event-queue not updating

So I'm writing a program with an event system.
I got a list of events to be handled.
One Process is supposed to push to the handler-list new events.
This part seems to work as I tried to print out the to-handle-list after pushing one event.
It gets longer and longer, while, when I print out the to handle list in the handle-event method, it is empty all the time.
Here is my event_handler code:
class Event_Handler:
def __init__(self):
self._to_handle_list = [deque() for _ in range(Event_Prio.get_num_prios()) ]
self._controll_handler= None
self._process_lock = Lock()
def init(self, controll_EV_handler):
self._controll_handler= controll_EV_handler
def new_event(self, event): #adds a new event to list
with self._process_lock:
self._to_handle_list[event.get_Prio()].append(event) #this List grows
def handle_event(self): #deals with the to_handle_list
self._process_lock.acquire()
for i in range(Event_Prio.get_num_prios()): #here i keep a list of empty deque
print(self._to_handle_list)
if (self._to_handle_list[i]): #checks if to-do is empty, never gets here that its not
self._process_lock.release()
self._controll_handler.controll_event(self._to_handle_list[i].popleft())
return
self._process_lock.release()
def create_Event(self, prio, type):
return Event(prio, type)
I tried everything. I checked if the event-handler-id is the same for both processes (plus the lock works)
I even checked if the to-handle-list-id is the same for both methods; yes it is.
Still the one in the one process grows, while the other is empty.
Can someone please tell me why the one list is empty?
Edit: It works just fine if I throw a event through the system with only one process. has to do sth with multiprocessing
Edit: Because someone asked, here is a simple usecase for it(I only used the essentials):
class EV_Main():
def __init__(self):
self.e_h = Event_Handler()
self.e_controll = None #the controller doesnt even matter because the controll-function never gets called....list is always empty
def run(self):
self.e_h.init(self.e_controll)
process1 = Process(target = self.create_events)
process2 = Process(target = self.handle_events)
process1.start()
process2.start()
def create_events(self):
while True:
self.e_h.new_event(self.e_h.create_Event(0, 3)) # eEvent_Type.S_TOUCH_EVENT
time.sleep(0.3)
def handle_events(self):
while True:
self.e_h.handle_event()
time.sleep(0.1)
To have a shareable set of deque instances, you could create a special class DequeArray which will hold an internal list of deque instances and expose whatever methods you might need. Then I would turn this into a shareable, managed object. When the manager creates an instance of this class, what is returned is a proxy to the actual instance that resides in the manager's address space. Any method calls you make on this proxy are actually shipped of to the manager's process using pickle and any results returned the same way. Since the individual deque instances are not shareable, managed objects, do not add a method that returns one of these deque instances which is then modified without being cognizant that the version of the deque in the manager's address space has not been modified.
Individual operations on a deque are serialized. But if you are doing some operation on a deque that consists of multiple method calls on the deque and you require atomicity, then that sequence is a critical section that needs to be done under control of a lock, as in the left_rotate function below.
from multiprocessing import Process, Lock
from multiprocessing.managers import BaseManager
from collections import deque
# Add methods to this as required:
class DequeArray:
def __init__(self, array_size):
self._deques = [deque() for _ in range(array_size)]
def __repr__(self):
l = []
l.append('DequeArray [')
for d in self._deques:
l.append(' ' + str(d))
l.append(']')
return '\n'.join(l)
def __len__(self):
"""
Return our length (i.e. the number of deque
instances we have).
"""
return len(self._deques)
def append(self, i, value):
"""
Append value to the ith deque
"""
self._deques[i].append(value)
def popleft(self, i):
"""
Eexcute a popleft operation on the ith deque
and return the result.
"""
return self._deques[i].popleft()
def length(self, i):
"""
Return length of the ith dequeue.
"""
return len(self._deques[i])
class DequeArrayManager(BaseManager):
pass
DequeArrayManager.register('DequeArray', DequeArray)
# Demonstrate how to use a sharable DequeArray
def left_rotate(deque_array, lock, i):
# Rotate first element to be last element:
# This is not an atomic operation, so do under control of a lock:
with lock:
deque_array.append(i, deque_array.popleft(i))
# Required for Windows:
if __name__ == '__main__':
# This starts the manager process:
with DequeArrayManager() as manager:
# Two deques:
deque_array = manager.DequeArray(2)
# Initialize with some values:
deque_array.append(0, 0)
deque_array.append(0, 1)
deque_array.append(0, 2)
# Same values in second deque:
deque_array.append(1, 0)
deque_array.append(1, 1)
deque_array.append(1, 2)
print(deque_array)
# Both processses will be modifying the same deque in a
# non-atomic way, so we definitely need to be doing this under
# control of a lock. We don't care which process acquires the
# lock first because the results will be the same regardless.
lock = Lock()
p1 = Process(target=left_rotate, args=(deque_array, lock, 0))
p2 = Process(target=left_rotate, args=(deque_array, lock, 0))
p1.start()
p2.start()
p1.join()
p2.join()
print(deque_array)
Prints:
DequeArray [
deque([0, 1, 2])
deque([0, 1, 2])
]
DequeArray [
deque([2, 0, 1])
deque([0, 1, 2])
]

Trying to save node or reference to node in a list

I have a tree class in which the class gets initialized with a data, left, and right attributes.
in the same class I have a "save" method.
I am using a list as a queue.
I am attempting to create a "save" method which takes only one argument "data".
The purpose of this save method is to dequeue from my list, check that node to see if its empty and if it is then it saves my data there. Otherwise it enqueues the 2 children of that node into the list.
The purpose of this is to save data in level order into the tree.
Because the class gets initialized there is always at least 1 element in the tree which is the root node.
The issue i keep running into is that whenever i append the self.data (the root node, not the data im currently trying to add) into my list at the beginning of the save method it only saves the data there.
and obviously when I then try to append the left and right child of this int i get an error because the int has no left or right attributes.
I am wondering how to save the node in the list instead of the data at the node.
class Tree():
aqueue = []
def __init__(self, item):
self.item = item
self.leftchild = None
self.rightchild = None
self.aqueue.append(self.item)
def add(self, newitem):
temp = self.myqueue.pop(0)
if temp is None:
temp = Tree(newitem)
else:
self.aqueue.append(temp.leftchild)
self.aqueue.append(temp.rightcild)
temp.add(newitem)
self.aqueue.clear() #this is meant to clear queue of all nodes after the recursions are complete
self.aqueue.append(self.item) #this is meant to return the root node to the queue so that it is the only item for next time
There are a couple of obvious issues with your code: both the if and else branch return, so the code after will never run, temp == newitem is an equality expression, but even if it was an assignment it wouldn't do anything:
def add(self, newitem):
temp = self.myqueue.pop(0)
if temp == None: # should use temp is None
temp == newitem # temp = newitem still wouldn't do anything
return True
else:
self.aqueue.append(temp.leftchild)
self.aqueue.append(temp.rightcild)
return temp.add(newitem)
# you will never get here, since both branches of the if returns
self.aqueue.clear() # delete everything in the list..?
self.aqueue.append(self.item)

How to pass two arguments with one variable into a function?

I have been given a class which implements a Priority Queue , using a function to evaluate the priority.
class PriorityQueueWithFunction(PriorityQueue):
"""
Implements a priority queue with the same push/pop signature of the
Queue and the Stack classes. This is designed for drop-in replacement for
those two classes. The caller has to provide a priority function, which
extracts each item's priority.
"""
def __init__(self, priorityFunction):
# type: (object) -> object
"priorityFunction (item) -> priority"
self.priorityFunction = priorityFunction # store the priority function
PriorityQueue.__init__(self) # super-class initializer
def push(self, item):
"Adds an item to the queue with priority from the priority function"
PriorityQueue.push(self, item, self.priorityFunction(item))
I have been also , given , the priority function that I am going to initialize the class above with.
def manhattanHeuristic(position, problem, info={}):
"The Manhattan distance heuristic for a PositionSearchProblem"
xy1 = position
xy2 = problem.goal
return abs(xy1[0] - xy2[0]) + abs(xy1[1] - xy2[1])
The above code is given to us and we cannot change it. I must create that PriorityQueueWithFunction Class and push an element to it. The push function of my class takes on argument , the item. But my PriorityFunction takes 2.
What kind of arguments should i use to push the right elemnt into my class and also make my priorityfunction work properly ?
That's what i tried and i am getting compiling errors , manhattanHeuristic...takes 2 arguments , 1 given
#Creating a queingFn
queuingFn = PriorityQueueWithFunction(heuristic)
Frontier = queuingFn
#Creating the item that needs to be pushed
StartState = problem.getStartState()
StartNode = (StartState,'',0,(-1,-1))
#Here is my problem
item = StartState , problem
Frontier.push(item)
Should I change my item's form ? Any ideas ?
You should make a new method that wraps call to manhattanHeuristic:
# for item as dict: item = {'position': POS, 'problem': PROBLEM}
def oneArgHeuristic(item):
position = item.position
problem = item.problem
return manhattanHeuristic(position, problem)
# for item as tuple: item = (POS, PROBLEM)
def oneArgHeuristic(item):
position, problem = item
return manhattanHeuristic(position, problem)
and pass it to PriorityQueueWithFunction instead of the original one

Forkable iterator - is there any implementations of it in Python?

What I mean by "forkable iterator" - it is a regular iterator with method fork() which creates a new iterator which iterates from the current point of iteration of original iterator. And even if the original iterator was iterated further, fork will stay at the point where it was forked, until it itself will not be iterated over.
My practical use case:
I have a socket connection, and some "packets" that sent through it. Connection can be shared between "receivers" and each "packet" can be addressed to some "receiver". "Packets" can come in unordered way, so each "receiver" can potentially receive packet for different "recevier". And more than that - if one "receiver" received "packet" for different "recevier", this "different receiver" must still be able to read that packet.
So for that I want to implement such forkable iterator, which will represent the connection, and each receiver will make own fork, read it and search for "packets" addressed for it.
Does somebody know any implementations of what I'm talking about?
You are looking for the itertools.tee() function:
Return n independent iterators from a single iterable.
Do take into account that the implementation will buffer data to service all child iterators:
This itertool may require significant auxiliary storage (depending on how much temporary data needs to be stored).
Also, you should only use the returned child iterators; iterating over the source iterator will not propagate the data to the tee() iterables.
Thats my current implementation of forkable iterator:
#!/usr/bin/env python
# coding=utf-8
from collections import Iterator, deque
import threading
class ForkableIterator(Iterator):
def __init__(self, iterator, buffer=None, *args, **kwargs):
self.iterator = iter(iterator)
if buffer is None:
self.buffer = deque()
else:
self.buffer = buffer
args = iter(args)
self.refs = kwargs.get('refs', next(args, {}))
self.refs.setdefault('base', 0)
self.pointer = kwargs.get('pointer', next(args, 0))
self.lock = kwargs.get('lock', next(args, threading.Lock()))
#property
def pointer(self):
return self.refs[self] + self.refs['base']
#pointer.setter
def pointer(self, value):
self.refs[self] = value
def __del__(self):
del self.refs[self]
def __iter__(self):
return self
def next(self):
with self.lock:
if len(self.buffer) - self.pointer == 0:
elem = next(self.iterator)
self.buffer.append(elem)
else:
if self.pointer == min(self.refs.itervalues()):
elem = self.buffer.popleft()
self.refs['base'] -= 1
else:
elem = self.buffer[self.pointer]
self.pointer += 1
return elem
def fork(self):
return self.__class__(self.iterator, self.buffer,
refs=self.refs, pointer=self.pointer,
lock=self.lock)

'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

Categories

Resources