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
Related
So I've been learning some Python by trying to code a game, and as I was making an object that moves between lists in other objects I appended the object into another list. Here is the code:
#Superclass for all materials
class Material():
def __init__(self,quantity,durability):
self.quantity=quantity
self.durability=durability
def damage(self,damage):
if damage>self.quantity:
damage=self.quantity
self.quantity=self.quantity-(damage-self.durability)
return damage
class Bio(Material):
def __init__(self,quantity):
super().__init__(quantity,0)
class Metal(Material):
def __init__(self,quantity):
super().__init__(quantity,40)
class Heap():
def __init__(self):
self.contents=[]
def deposit(self,material):
v=False
for i in self.contents:
if type(i) == type(material):
i.quantity=i.quantity+material.quantity
v=True
break
if v is False:
self.contents.append(material)
#Superclass for all organs
class Organ():
def __init__(self,material):
self.material=material
self.max=material.quantity
self.kill_me=False
def donate(self,amount,target,location): #Target has to be another Organ
stuff=self.material.damage(amount)
target.material.quantity=target.material.quantity+stuff
target.spill(location)
if self.material.quantity <= 0:
self.kill_me=True
def spill(self,location):
if self.material.quantity > self.max:
extra=self.material
extra.quantity=self.material.quantity-self.max
self.material.quantity=self.max
location.inhabitants[0].deposit(extra)
class Unit():
def __init__(self,organs,owner): #organs is a list of organ objects
self.organs=organs
self.owner=owner
self.kill_me=False
def cleanse(self):
for organ in self.organs:
if organ.kill_me == True:
self.organs.remove(organ)
def move(self,location,destination):
destination.inhabitants.append(self)
if self in destination.inhabitants and self in location.inhabitants:
print('Oh no')
else:
self.kill_me=True
class Location():
def __init__(self):
self.inhabitants=[]
self.inhabitants.append(Heap())
def cleanse(self):
for i in self.inhabitants:
if issubclass(type(i),Unit) == True and i.kill_me == True:
self.inhabitants.remove(i)
#Testing Code
crust=Location()
orbit=Location()
test=Organ(Bio(50))
twotest=Organ(Bio(50))
shuttle=Unit([test,twotest],True)
crust.inhabitants.append(shuttle)
shuttle.move(crust,orbit)
crust.cleanse()
for i in crust.inhabitants:
print(i)
if type(i) == Unit:
print(i.kill_me)
print('. . .')
for i in orbit.inhabitants:
print(i)
if type(i) == Unit:
print(i.kill_me)
print('. . .')
crust.inhabitants[1].kill_me=True
for i in crust.inhabitants:
print(i)
if type(i) == Unit:
print(i.kill_me)
print('. . .')
for i in orbit.inhabitants:
print(i)
if type(i) == Unit:
print(i.kill_me)
This is the output:
Oh no
<__main__.Heap object at 0x000002432F97B608>
<__main__.Unit object at 0x000002432F97B748>
False
. . .
<__main__.Heap object at 0x000002432F97B5C8>
<__main__.Unit object at 0x000002432F97B748>
False
. . .
<__main__.Heap object at 0x000002432F97B608>
<__main__.Unit object at 0x000002432F97B748>
True
. . .
<__main__.Heap object at 0x000002432F97B5C8>
<__main__.Unit object at 0x000002432F97B748>
True
I guess this happened because I didn't remove the "shuttle" from its previous location. However, trying to change the "kill_me" value changes both, rendering "cleanse" useless. However, I finished writing the possessing of the Unit.move location data (setting it to remove itself from the previous list) and it seems to have worked.
Regardless, I still have a few pressing questions:
How did that object become part of two lists?
Is there any practical use for this behavior?
Is there any built-in function that can allow an object to know what list it is nested in, or will I always have to feed that into the object's methods as I have been doing? (I've not been storing the location class using init & "self" because the location will likely change over time so I don't want to store an outdated version of it)
Finally, since I'm a beginner, is there any pressing thing in my code that I should definitely be aware of that will cause untold problems later or am I fine for now?
I have a function on Python get_object_by_id, that restores object by its id, calling different functions depending on the type of the object:
def get_object_by_id(object_id: int) -> tp.Union[int, float, tuple, list, str, bool]:
"""
Restores object by id.
:param object_id: Object Id.
:return: An object that corresponds to object_id.
"""
info = struct.unpack("LL", ctypes.string_at(object_id, 16))
if info[1] == id(int):
return get_int_by_id(object_id)
elif info[1] == id(float):
return get_float_by_id(object_id)
elif info[1] == id(bool):
return get_bool_by_id(object_id)
elif info[1] == id(str):
return get_str_by_id(object_id)
elif info[1] == id(list):
return get_list_by_id(object_id)
elif info[1] == id(tuple):
return get_tuple_by_id(object_id)
else:
return None
My function get_list_by_id restores lists recursively:
def get_list_by_id(object_id: int) -> list:
info = struct.unpack("5L", ctypes.string_at(object_id, 40))
size_of_list = str(info[2]) + 'L'
elements_ides = struct.unpack(size_of_list, ctypes.string_at(info[3], 8 * info[2]))
res_list = []
for i in range(info[2]):
res_list.append(get_object_by_id(elements_ides[i]))
return res_list
It works well if nested lists are not very deep, but exceeds maximum recursion depth otherwise. I'm new to Python, and I struggle to understand, how can I rewrite this function without recursion and not make it looking monstrous.
Well, I didn't test it, so I don't know if it really works, but hopefully it makes the point: if the system stack won't do it, make your own stack.
def get_list_by_id(object_id: int) -> list:
stack_im_working_on = [] # maybe dqueue is faster?
# records are [info, elements_ides, 2=res_list, 3=i]
def push_new_list(object_id: int) -> list:
info = struct.unpack("5L", ctypes.string_at(object_id, 40))
size_of_list = str(info[2]) + 'L'
elements_ides = struct.unpack(size_of_list, ctypes.string_at(info[3], 8 * info[2]))
res_list = []
nonlocal stack_im_working_on
stack_im_working_on.append([info, elements_ides, res_list, 0])
push_new_list(object_id) # start from working on this
while True: # work from top of the stack
info, elements_ides, res_list, i = stack_im_working_on[-1]
while i < info[2]:
if info[1] == id(list): # The recursive call does not happen
push_new_list(elements_ides[i]) # Now we work on this
break # go to while stack_im_working_on
else:
res_list.append(get_object_by_id(elements_ides[i]))
# res_list is shared with the stack frame, but i is not.
stack_im_working_on[-1][3] = i = i + 1 # save that progress
else: # else for while... run when it gets to the end, until NOT i < info[2](and not on break)
# we finished this stack frame, so return the answer
stack_im_working_on.pop() # removes last element (that we just finished)
if stack_im_working_on:
# return to prev stack frame (not done yet)
stack_im_working_on[-1][2].append(res_list)
else:
# return to caller
return res_list
# Not Reached, as the only pop() checks for empty above
I hear that people don't like the "else" at the end of a loop, but it really is useful. (I always put a comment on it)
On the other hand, if your stack really won't ever be that huge, and you can predict a max size... just increase the system stack size limit. (it looks alot easier)
https://stackoverflow.com/questions/3323001/what-is-the-maximum-recursion-depth-in-python-and-how-to-increase-it
import sys
sys.setrecursionlimit(1500)
I know my question sounds weird, but I am searching for this but I can't find it nowhere. I want to simulate a TableScan statement from SQL with printing out a list of lists, so I call the method next() with the object 'x' as long as ("EOF" of list) is not returned. But if I write
while(x.next() != "EOF"): the function next() is already called once and this not what I want, because I skip already one tuple.
Here the code:
class TableScan(Iterator):
def __init__(self, collection):
super().__init__()
self.collection = collection
self.iter = None
def open(self):
self.iter = iter(self.collection)
def next(self):
try:
while(self.iter != None):
return next(self.iter)
except StopIteration:
return "EOF"
# The list.
cS = [[101,2,3,5,1],
[202,4,99,2,4],
[303,2,4,6,8],
[404,1,23,4,6],
[505,2,22,4,5]]
# Making object x and calling constructor of class TableScan.
x = TableScan(cS)
while(x.next() != "EOF"): ###Problem- lines###
print(x.next())
Can somebody please help me?
Assign the result to a variable so you can test it and print it.
while True:
n = x.next()
if n == 'EOF':
break
print(n)
i know this has an answer, but in python 3.8 and above you can do:
while (n := x.next()) != 'EOF':
print(n)
I have a list with words in two languages where each foreign word is followed (on the next row) by its meaning in a known language. Example:
hablar
talk
llamar
call
Now I wish to create a vocabulary test using queues. My idea is to create 2 queues q1 and q2. All the words start in q1 until each word's meaning has been guessed correctly. If you get a word wrong, the word will get placed in the end of the queue of q1 and if you get it right, it will be moved to q2. When q1 is empty, you move over to q2 and do the same thing, except the words get 'thrown away' when you answer correctly and the test is done once q2 is empty.
The problem is I can't figure out how to create a way to associate the foreign word with the known word. I think I should start like this:
class Wordpair():
def __init__(self, l1, l2):
self.lang1 = l1
self.lang2 = l2
def __str__(self):
question=input('What does'+self.lang1+'mean?')
But I don't know how to test if the preson answers correctly or wrongly. Also, I think I could somehow implement nodes since the meaning of the word (Node) will be the next word (Node.next). I will update as I make progress, but I'd appreciate any tips you have now.
Edit1: This is how I created the queue:
class Queue:
def __init__(self):
self.items = []
def put(self, item):
self.items.append(item)
def get(self):
return self.items.pop(0)
def isempty(self):
return self.items == []
You can simply compare the user input with the known meaning of the word.
I have written a simple script(Python3) for you to solve this problem, hope it helps!
import queue
class Word(object):
def __init__(self, foreign_meaning, known_meaning):
self.foreign_meaning = foreign_meaning
self.known_meaning = known_meaning
if __name__ == '__main__':
q1 = queue.Queue()
q2 = queue.Queue()
# Put some sample words
q1.put(Word('hablar', 'talk'))
q1.put(Word('llamar', 'call'))
while True:
if q1.empty():
print("You have finished all words!")
break
word = q1.get() # Get the next word in q1
ans = input("What is the meaning of `{0}`? ".format(word.foreign_meaning)) # Fetch user input as the answer
if ans == word.known_meaning:
print("Correct!")
q2.put(word)
else:
print("Wrong! The meaning of `{0}` is `{1}`".format(word.foreign_meaning, word.known_meaning))
q1.put(word)
print()
Looks like that you are using your own queue implementation.
I have modified my code to fit the question. However, it is strongly recommended that you use the built-in queue module provided by Python3 as it is thread safe.
#!/usr/bin/env python
class Queue:
def __init__(self):
self.items = []
def put(self, item):
self.items.append(item)
def get(self):
return self.items.pop(0)
def isempty(self):
return self.items == []
class Word(object):
def __init__(self, foreign_meaning, known_meaning):
self.foreign_meaning = foreign_meaning
self.known_meaning = known_meaning
if __name__ == '__main__':
q1 = Queue()
q2 = Queue()
# Put some sample words
q1.put(Word('hablar', 'talk'))
q1.put(Word('llamar', 'call'))
while True:
if q1.isempty():
print("You have finished all words!")
break
word = q1.get() # Get the next word in q1
ans = input("What is the meaning of `{0}`? ".format(word.foreign_meaning)) # Fetch user input as the answer
if ans == word.known_meaning:
print("Correct!")
q2.put(word)
else:
print("Wrong! The meaning of `{0}` is `{1}`".format(word.foreign_meaning, word.known_meaning))
q1.put(word)
print()
In this case, I would just use a list for each word. I don't think you really need a new class. The program I ended up with is a little long (note this is python 2):
#!/usr/bin/env python
from Queue import Queue
FILENAME='words.txt'
def main():
q1 = readwords()
q2 = Queue()
while (not q1.empty()) or (not q2.empty()):
if not q1.empty():
src = 1
word = q1.get()
else:
src = 2
word = q2.get()
ans = input('What does "'+word[0]+'" mean? ')
if ans==word[1]:
print 'Correct!'
src += 1
else:
print 'Incorrect! "'+word[1]+'"'
if src==1:
q1.put(word)
elif src==2:
q2.put(word)
print 'Done! Good job!'
def readwords():
with open(FILENAME,'r') as f:
lines = f.readlines()
first = True
words = Queue()
word = [None,None]
for x in lines:
if not x.strip():
continue
if first:
word[0] = x.strip()
first = False
else:
word[1] = x.strip()
first = True
words.put(word)
word = [None,None]
return words
if __name__ == '__main__':
main()
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.