Why the menu does not start (solved by Roman Susi)
Why the menu do not work as expected (error below)
How do I solve the error in my foo.add code?
Traceback (most recent call last):
File "C:\Users\User\Desktop\phonedatabase.py", line 81, in <module>
openphonedb()
File "C:\Users\User\Desktop\phonedatabase.py", line 23, in openphonedb
for entry in foo.add(name, number, showtype):
TypeError: 'NoneType' object is not iterable
This error happens when adding a new user, after typing in the 'Type'
import shelve
import string
UNKNOWN = 0
HOME = 1
WORK = 2
FAX = 3
CELL = 4
def openphonedb():
foo = phonedb()
print "What would you like to do?"
print "Add = 1, Lookup = 2, Exit = 3"
entry = int(raw_input('>> '))
if entry == 1 :
namelookup = raw_input('Please enter a name: ')
for entry in foo.lookup(namelookup):
print '%-40s %s (%s)' % (entry.name, entry.number, entry.showtype() )
elif entry == 2:
name = raw_input('Name: ')
number = raw_input('Number: ')
showtype = input('Type (UNKNOWN, HOME, WORK, FAX, CELL): \n>> ')
for entry in foo.add(name, number, showtype):
print '%-40s %s (%s)'% (entry.name, entry.number, entry.showtype() )
elif entry == 3:
print "Close Successful"
quit
else:
print "Invalid."
openphonedb()
class phoneentry:
def __init__(self, name = 'Unknown', number = 'Unknown',
type = UNKNOWN):
self.name = name
self.number = number
self.type = type
# create string representation
def __repr__(self):
return('%s:%d' % ( self.name, self.type ))
# fuzzy compare or two items
def __cmp__(self, that):
this = string.lower(str(self))
that = string.lower(that)
if string.find(this, that) >= 0:
return(0)
return(cmp(this, that))
def showtype(self):
if self.type == UNKNOWN: return('Unknown')
if self.type == HOME: return('Home')
if self.type == WORK: return('Work')
if self.type == FAX: return('Fax')
if self.type == CELL: return('Cellular')
class phonedb:
def __init__(self, dbname = 'phonedata'):
self.dbname = dbname;
self.shelve = shelve.open(self.dbname);
def __del__(self):
self.shelve.close()
self.shelve = None
def add(self, name, number, type = HOME):
e = phoneentry(name, number, type)
self.shelve[str(e)] = e
def lookup(self, string):
list = []
for key in self.shelve.keys():
e = self.shelve[key]
if cmp(e, string) == 0:
list.append(e)
return(list)
#edit
if __name__ == '__main__':
openphonedb()
Maybe, you just forgot to call the openphonedb()?
Add to the end:
if __name__ == '__main__':
openphonedb()
Also, what "quit" is doing there?
code has other issues, but with regard to the first part of the question, what about comparing entry as a string (so if an user types "a" you don't get an error)?
def openphonedb():
foo = phonedb()
print "What would you like to do?"
print "Add = 1, Lookup = 2, Exit = 3"
while True: # note this
entry = raw_input('>> ') # removed int()
if entry == '1' :
namelookup = raw_input('Please enter a name: ')
for entry in foo.lookup(namelookup):
print '%-40s %s (%s)' % (entry.name, entry.number, entry.showtype() )
elif entry == '2':
name = raw_input('Name: ')
number = raw_input('Number: ')
showtype = input('Type (UNKNOWN, HOME, WORK, FAX, CELL): \n>> ')
for entry in foo.add(name, number, showtype):
print '%-40s %s (%s)'% (entry.name, entry.number, entry.showtype() )
elif entry == '3':
print "Close Successful"
exit() # note this also
else:
print "Invalid."
Related
I need to re-use a script I wrote in Python 3.10 using Python 2.7; when I change the interpreter to 2.7, script below errors with following message: TypeError: unbound method CheckInput() must be called with Elem instance as first argument (got int instance instead)
Trying to resolve this for hours but I'm a beginner and am definitely missing something. Aim of the program is to add a few values as user input and later on print them out. Code below:
class Elem():
Elem_count = 0
def CheckInput(input):
try:
# Convert it into integer
val = int(input)
except ValueError:
try:
# Convert it into float
val = float(input)
except ValueError:
print("You have entered a string, please use numbers!")
def Add_Elem(self):
if Elem.Elem_count == 0:
print('Enter first Elem info:')
self.width = input('width: ')
Elem.CheckInput(self.width)
self.height = input('Height: ')
Elem.CheckInput(self.height)
self.depth = input('depth: ')
Elem.CheckInput(self.depth)
else:
print('Enter second Elem info:')
self.width = input('width: ')
Elem.CheckInput(self.width)
self.height = input('Height: ')
Elem.CheckInput(self.height)
self.depth = input('depth: ')
Elem.CheckInput(self.depth)
Elem.Elem_count += 1
if Elem.Elem_count > 2:
exit
def Display_Elem(self):
print('\n')
if Elem.Elem_count == 0:
print('Element ')
print('width: ' + self.width)
print('Height: ' + self.height)
print('Depth: ' + self.depth)
else:
print('Element ')
print('width: ' + self.width)
print('Height: ' + self.height)
print('Depth: ' + self.depth)
def main():
First_Elem = Elem()
Second_Elem = Elem()
First_Elem.Add_Elem()
Second_Elem.Add_Elem()
print ("Elements added:")
First_Elem.Display_Elem()
Second_Elem.Display_Elem()
if __name__ == "__main__":
main()
Your issue is here:
def CheckInput(input):
For a normal class method, you'll have a definition like this:
def my_method(self, some_parameter):
The self here refers to the class. While you can pass in some other class, the behavior quickly becomes undefined. Your TypeError points to this, though: CheckInput() must be called with Elem instance as first argument (got int instance instead).
This means an int was passed - which is likely the parameter you meant. All you need is this:
def CheckInput(self, candidate_input):
try:
val = int(candidate_input)
except ValueError:
try:
val = float(candidate_input)
except ValueError:
print(f"Could not convert '{candidate_input}' to a number!")
return val
Note the change of input to candidate_input to avoid builtin name collision, and the use of the candidate input in the output string to allow the user to understand what was happening with bad input.
Also, it's likely that you want to return the value that you have - though it's not great design to have a function that returns one of two types of numbers.
To me the easiest fix would be to remove the checkinput method from your elem class ; it is useless for it to be in the class because it doesn't use the attributes of the class.
Also, you shouldn't name a variable "input" as it is the name of a builtin in both Python 2 and Python 3.
def CheckInput(data):
try:
# Convert it into integer
val = int(data)
except ValueError:
try:
# Convert it into float
val = float(data)
except ValueError:
print("You have entered a string, please use numbers!")
class Elem():
Elem_count = 0
def Add_Elem(self):
if Elem.Elem_count == 0:
print('Enter first Elem info:')
self.width = input('width: ')
CheckInput(self.width)
self.height = input('Height: ')
CheckInput(self.height)
self.depth = input('depth: ')
CheckInput(self.depth)
else:
print('Enter second Elem info:')
self.width = input('width: ')
CheckInput(self.width)
self.height = input('Height: ')
CheckInput(self.height)
self.depth = input('depth: ')
CheckInput(self.depth)
Elem.Elem_count += 1
if Elem.Elem_count > 2:
exit
def Display_Elem(self):
print('\n')
if Elem.Elem_count == 0:
print('Element ')
print('width: ' + self.width)
print('Height: ' + self.height)
print('Depth: ' + self.depth)
else:
print('Element ')
print('width: ' + self.width)
print('Height: ' + self.height)
print('Depth: ' + self.depth)
Using my current setup on my code; how do i output only the False objects ("hasBeenRead = False")
#An SMS Simulation
SMSStore = []
unreadMessage = []
class SMSMessage(object):
def __init__(self, messageText, fromNumber):
self.hasBeenRead = False
self.messageText = messageText
self.fromNumber = fromNumber
def markAsRead(self, hasBeenRead):
hasBeenRead = True
def add_sms(self):
newMessage = (self.hasBeenRead, self.messageText, self.fromNumber)
return SMSStore.append(newMessage)
def get_count(self):
return len(SMSStore)
def get_message(self, q):
print (SMSStore[q][1])
self.get_hasBeenRead()
def get_hasBeenRead(self):
self.hasBeenRead = True
def get_unread_messages(SMSStore):
counter = 0
if SMSStore[counter][0] == False:
print "From: " + SMSStore[counter][2]
print "Message: " + SMSStore[counter][1]
counter = counter +1
def remove(self, i):
return SMSStore.remove(i)
#sample = SMSMessage("Hello friend!", 0742017560)
userChoice = ""
while userChoice != "quit":
userChoice = raw_input("What would you like to do - read/send/quit?")
if userChoice == "read":
i = int((raw_input("Please enter which messsage number you want to read: ")))
messageText = "null"
fromNumber = "null"
newObject1 = SMSMessage(messageText, fromNumber)
newObject1.get_message(i)
readUnread = raw_input("Would you like to read the unread messages: yes/no?")
if readUnread == "yes":
newObject1.get_unread_messages()
else:
print "All messages have been read"
elif userChoice == "send":
messageText = raw_input("Please type in your message: ")
fromNumber = raw_input("Please type in the number it was sent from ")
newObject = SMSMessage(messageText, fromNumber)
newObject.add_sms()
print str(newObject.get_count()) + " is now the new length of the list"
elif userChoice == "quit":
print "Goodbye"
else:
print "Oops - incorrect input"
As you can see i am quiet a beginner at coding but using what i have setup is it possible to only output objects from the list that have False?
I have been programming a piece of code to try and carry through a class from one function to another (the code is also broken in other ways but those aren't the important ones). The major problem if you define a class in the enter function it then gives the error:
exec("""print({}.Show())""".format(x))
File "<string>", line 1, in <module>
NameError: name (whatever I have called the class title) is not defined
in the tr function.
import pickle
import traceback
import sys
classtitles = []
class Customer(object):
def __init__(self):
try:
self.load()
print(self.customer)
except:
None
def init2(self,customer_name,home_address,telephone_number):
self.customer = customer_name
self.address = home_address
self.phone = telephone_number
print(self.customer)
classtitles.append(self.customer)
def carpet_amounts(self, carpet_type, grippers_bool):
self.type = carpet_type
self.grippers = grippers_bool
def price(self, size, perimeter):
self.size = size
self.perimeter = perimeter
self.price = 0
if self.type == "First":
self.price = float(5.99) * self.size
if self.type == "Monarch":
self.price = float(7.99) * self.size
if self.type == "Royal":
self.price = int(60) * self.size
price_add = float(22.5) * self.size
if self.grippers == True:
price_add += self.perimeter * float(1.10)
hours = 0
while size >= 16:
hours += 1
size -= 16
self.hours = hours
price_add += hours * 65
self.price += price_add
def Show(self):
print("show")
if self.grippers == True:
grips = "with"
else:
grips = "without"
return ("the size is {}m^2 and with a {} undercarpet and {} grippers, totalling more than {} hours of work is {}".format(self.size,self.type,grips,self.hours,self.price))
def save(self):
"""save class as self.name.txt"""
file = open('ClassSave.txt','wb')
file.write(pickle.dumps(self.__dict__))
file.close()
def load(self):
"""try load self.name.txt"""
file = open('ClassSave.txt','r')
datapickle = file.read()
file.close()
self.__dict__ = pickle.loads(dataPickle)
def loadf():
f = open('classnames.txt','r')
mylist = f.read().splitlines()
for x in mylist:
exec("""{} = Customer()""".format(mylist[0]))
customs()
def customs():
try1 = input("Would you like to 1. Enter a new customer. 2. View all the customers. 3. Delete an old customer")
if try1 == '1':
enter()
elif try1 == 'q':
sys.exit()
else:
tr()
def enter():
name = input("What is thr customers name (no space i.e. 'JoeBloggs')? ")
address = input("What is their address")
phonenumber = str("What is their phone number")
exec("""{} = Customer()""".format(name))
exec("""{}.init2("{}","{}","{}")""".format(name,name,address,phonenumber))
print(classtitles)
carpet_type = input("What type of carpet would they like ('First','Monarch','Royal')? ")
grips = str(input("Would they like grips (1 = yes, 2 = no)? "))
if grips == '1':
grips = True
else:
grips = False
exec("""{}.carpet_amounts("{}",{})""".format(name,carpet_type,grips))
size = int(input("What is the m^2 size of their carpet? "))
perimeter = int(input("What is the m perimeter of their carpet? "))
exec("""{}.price({},{})""".format(name,size,perimeter))
exec("print({}.Show())".format(name))
file2 = open('classnames.txt','w')
for x in classtitles:
file2.write(x)
file2.close()
exec("{}.save()".format(name))
customs()
def tr():
x = input("name")
print(x)
exec("""print({}.Show())""".format(x))
customs()
loadf()
I have an employee class which has an init method that reads an employees record in from a file. I also have an employees class which has an init_ method that attempts to read in all of the employee records.
I am having trouble with init for the employees class. Here is my code:
class EmployeeList():
records=[]
def __init__(self):
with open(database) as fp:
emp=employee(fp)
while (emp.id > 0):
print(emp)
self.records.append(emp)
emp=employee(fp)
The print(emp) is there for error checking, it shows that the records are being read in properly. When the EOF is reached, the init method for the employee sets the id to 0 and the name of the employee to "". I have two problems:
After the loop, all of the employees in employees.records are the same - id 0 and blanks for names. I am assuming that that emp is not creating a new instance each time it is called, and so all of the employees are being set to that one instance of emp, the very last one from when EOF is reached.
I doubt my code is "Pythonesque"; suggestions for improvement are welcome.
P.S. database is globally defined to the file name.
The entire code is here, sorry about the length:
class employee:
count = 0
def __init__(self,f=None):
if (f==None): # a user is inputting the employee
self.lastname = input("Employees last name:")
while type(self.lastname)!=type("1"):
print("Your input needs to be a name\n")
self.lastname = input("Employees last name:")
self.firstname = input("Employees first name:")
while type(self.firstname)!=type("1"):
print("Your input needs to be a name\n")
self.firstname = input("Employees first name:")
self.payrate = float(input("Employees pay rate:"))
while type(self.payrate)!=type(0.0):
print("Your input needs to be a pay rate\n")
self.payrate = float(input("Employees pay rate:"))
employee.count = employee.count + 1
self.id = employee.count
else: # the employee is being read in from the database and f is a file pointer
# read in an employee record and return false for end of file.
checkEOF = f.readline().rstrip('\r\n') #check for end of file
if (checkEOF != ""):
employee.id = int(checkEOF)
employee.firstname = f.readline().rstrip('\r\n')
employee.lastname = f.readline().rstrip('\r\n')
employee.payrate = float(f.readline().rstrip('\r\n'))
else:
employee.id = 0
employee.firstname = " "
employee.lastname = " "
employee.payrate = 0.0
def __hash__(self):
return hash(self.id)
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.id == other.id
return NotImplemented
def __str__(self):
return "Employee " + str(self.id) + " is "+self.firstname + " "+self.lastname+" and their pay rate is "+str(self.payrate)+"\n"
def __lt__(self, other):
if (self.lastname < other.lastname):
return True
elif (self.lastname > other.lastname):
return False
else: #same last names
if (self.firstname < other.firstname):
return True
elif (self.firstname > other.firstname):
return False
else: #same names
if (self.id < other.id):
return True
else: # note that ids cannot be the same
return False
def __gt__(self, other):
if (self.lastname > other.lastname):
return True
elif (self.lastname < other.lastname):
return False
else: # Same last names
if (self.firstname > other.firstname):
return True
elif (self.firstname > other.firstname):
return False
else: # Same names
if (self.id > other.id):
return True
else: # note that ids cannot be the same
return False
def payraise(self,payraise):
self.payrate = self.payrate+payraise
def saveemployee(self,fp):
fp.write(str(self.id)+"\n")
fp.write(self.firstname+"\n")
fp.write(self.lastname+"\n")
fp.write(str(self.payrate)+"\n")
class EmployeeList():
records=[]
def __init__(self):
with open(database) as fp:
emp=employee(fp)
while (emp.id > 0):
print(emp)
self.records.append(emp)
emp=employee(fp)
def __str__(self):
employeesprint = ""
for emp in self.records:
employeesprint = employeesprint + str(emp)
return employeesprint
def save(self):
self.records.sort()
with open(database,"w+") as fp:
fp.seek(0)
for emp in self.records:
emp.saveemployee(fp)
def menu():
print("\n")
print(choices[0]+". Add another employee")
print(choices[1]+". Print employees")
print(choices[len(choices)-1]+". Quit")
print("\n")
employees = EmployeeList()
choices = ["A","B","C"]
ch = "N"
while (ch != choices[len(choices)-1]):
menu()
ch=input("Make your choice ")
while not (ch in choices):
menu()
ch=input("Make your choice ")
if (ch == choices[0]):
employees.records.append(employee())
employees.save()
if (ch == choices[1]):
print(employees)
Sample output: You can see the two employees correctly being printed as they are read in:
Employee 1 is jane bob and their pay rate is 1.0
Employee 2 is jim bob and their pay rate is 3.4
A. Add another employee
B. Print employees
C. Quit
Make your choice B
Employee 0 is and their pay rate is 0.0
Employee 0 is and their pay rate is 0.0
your code:
if (checkEOF != ""):
employee.id = int(checkEOF)
employee.firstname = f.readline().rstrip('\r\n')
employee.lastname = f.readline().rstrip('\r\n')
employee.payrate = float(f.readline().rstrip('\r\n'))
else:
employee.id = 0
employee.firstname = " "
employee.lastname = " "
employee.payrate = 0.0
change 'employee' to 'self', 'employee' is the name of the class.
import pickle
class TasksError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class Task(object):
def __init__(self, task = () ):
if task ==():
raise TasksError('Empty task.')
self.name = task[0]
self.date = task[1]
self.priority = task[2]
self.time = task[3]
self.type = task[4]
self.comment = task[5]
def __str__(self):
output = '''Name: %s
Date: %s
Priority: %s
Time: %s
Type: %s
Comment: %s
''' % ( self.name,
self.date,
self.priority,
self.time,
self.type,
self.comment)
return output
class Tasks(object):
def __init__(self, container = []):
self.container = [ Task(todo) for todo in container ]
def delete(self):
x = 0
for todo in self.container:
x = x + 1
print "Task Number",x,"\n", todo
delete = raw_input("what number task would you like to delete")
if delete == "y":
del todo
############
#x = 0
# for task in self.container:
# x = x+1
#print "Task Number",x,"\n", task
#delete = raw_input("what number task would you like to delete")
#if delete == "y":
#del(task)
def add(self, task):
if task == '':
raise TasksError('Empty task')
self.container.append( Task(task) )
def __str__(self):
output = '\n'.join( [ str(todo) for todo in self.container ] )
return output
if __name__== "__main__":
divider = '-' * 30 + '\n'
tasks = Tasks( container = [] ) # creates a new, empty task list
while True:
print divider, '''Make your selection:
1. Add new task
2. Print all tasks
3. Save tasks
4. Load tasks from disk
5. Find high priority tasks
6. Sort by date
7. Delete task
<ENTER> to quit
'''
try:
menu_choice = int(input("Select a number from the menu: "))
except:
print 'Goodbye!'
break
if menu_choice == 1:
task = raw_input (">>> Task: ")
date = raw_input (">>> Date as string YYYYMMDD: ")
priority = raw_input (">>> Priority: ")
time = raw_input (">>> Time: ")
Type = raw_input (">>> Type Of Task: ")
comment = raw_input (">>> Any Comments? ")
todo = (task, date, priority, time, Type, comment)
tasks.add( todo )
print tasks
elif menu_choice == 2:
print divider, 'Printing all tasks'
print tasks
elif menu_choice == 3:
print divider, 'Saving all tasks'
tasks.save()
elif menu_choice == 4:
print divider, 'Loading tasks from disk'
tasks.load()
elif menu_choice == 5:
print divider, 'Finding tasks by priority'
results = tasks.find_by_priority(priority='high')
for result in results: print result
elif menu_choice == 6:
print divider, 'Sorting by date'
tasks.sort_by_date()
print tasks
elif menu_choice == 7:
tasks.delete()
I have deleted parts of my code (hopefully nothing important).
Im having trouble getting python to delete my tasks once added.
Both methods defined as "def delete" give the error message type error: task/todo object does not support deletion.
Does anyone know a way around this?
You don't delete from list like that... Your code have 2 problems:
if you use for to loop through a iterable, you should not change it inside the loop.
to del from list you should use index.
Try this:
index = 0
while index < len(self.container):
delete = raw_input("what number task would you like to delete")
if delete == "y":
del self.container[index]
else:
index += 1