Why are some variables not defined? - python

This is what I have to do:
Look up and print the student GPA
Add a new student to the class
Change the GPA of a student
Change the expected grade of a student
Print the data of all the students in a tabular format
Quit the program
import student
import pickle
lookup = 1
change = 2
add = 3
delete = 4
QUIT = 0
FILENAME = 'student.dat'
def main():
students_info = load_students()
choice = 0
load_students()
#add(students_info)
change_grade(students_info)
change_GPA(students_info)
#get_menu_choice()
look_up(students_info)
while choice != QUIT:
choice = get_menu_choice()
if choice == lookup:
look_up(students_info)
elif choice == add:
add(students_info)
elif choice == change:
change(students_info)
elif choice == delete:
delete(students_info)
save_students(students_info)
def load_students():
try:
input_file = open(FILENAME, 'rb')
students_dict = pickle.load(input_file)
input_file.close()
except IOError:
students_dict = {}
print(students_dict)
return students_dict
def get_menu_choice():
print()
print('Menu')
print("-------------------")
print('1. Look up ID')
print('2.....')
choice = int(input("Enter your choice:"))
return choice
def look_up(students_info):
ID = input('Enter ID:')
print(student_info.get(ID, "Not found!"))
## try:
## print(students_info[ID])
## except KeyError:
## print("Not found!")
def change_GPA(students_info):
ID = input("ID:")
if ID in students_info:
GPA= float(input("New GPA:"))
students=student.Student(ID,GPA,grade,work)
students_info[ID] = students
print ("This",students_info[ID])
else:
print("Not found!")
def change_grade(students_info):
ID = input("ID:")
if ID in students_info:
New_grade = input("Enter new grade:")
students=student.Student(ID,GPA,grade,work)
students_info[ID] = students
#new_grade = students_info[name]
else:
print("Not found!")
def add(students_info):
name = input("Enter the student name:")
ID= input("Enter student's ID:")
GPA= float(input("Enter GPA:"))
grade= input("Enter student's expected grade:")
work = input("Does the student work part time or full time?")
students=student.Student(name,ID,GPA,grade,work)
print(students_info['ID'])
def save_students(students_info):
output_file = open(FILENAME, 'wb')
pickle.dump(students_info, output_file)
output_file.close()
main()
Whenever I tried to change the GPA or grade it's not defined. How could I change one value from the dictionary studens_info?

As gus42 has commented, the errors you are getting are from the lines:
students=student.Student(ID,GPA,grade,work)
You've not defined grade or work in either of the places you do this (nor GPA in change_grade), so it should not be surprising that you're getting an error.
I think there are two ways to fix the issue:
The simplest way is to change your logic from creating a new Student object to modifying the one that already exists. I don't know exactly what the attribute names are in your Student class, but here's a reasonable guess at a solution:
def change_GPA(students_info):
ID = input("ID:")
if ID in students_info:
GPA= float(input("New GPA:"))
students_info[ID].GPA = GPA # assign new GPA to old student object
else:
print("Not found!")
def change_grade(students_info):
ID = input("ID:")
if ID in students_info:
grade = input("Enter new grade:")
students_info[ID].grade = grade # assign new grade to existing student object
else:
print("Not found!")
The other option is to replace the existing Student object with a new one with some different values. This is close to what your current code, but it only really makes sense if your Student objects are immutable (perhaps because you made the type with namedtuple?). To make it work (where your current code does not), you'll have to load the old values from the old Student object before making the new object:
def change_GPA(students_info):
ID = input("ID:")
if ID in students_info:
new_GPA = float(input("New GPA:"))
old_grade = students_info[ID].grade # load old values
old_work = students_info[ID].work
new_student = students.Student(ID, new_GPA, old_grade, old_work)
students_info[ID] = new_student # replace the old student with a new object
else:
print("Not found!")
def change_grade(students_info):
ID = input("ID:")
if ID in students_info:
new_grade = input("Enter new grade:")
old_GPA = students_info[ID].GPA
old_work = students_info[ID].work
new_student = students.Student(ID, old_GPA, new_grade, old_work)
students_info[ID] = new_student
else:
print("Not found!")

Related

Writing File and Reading from File in python

import random
class Student:
#easy way or short way to printing student details
def student_details(self):
print("Student number :",self.student_number)
print("-----------")
print("First Name : ",self._firstname)
print("-----------")
print("Last Name : ",self._lastname)
print("-----------")
print("Date Of Birth : ",self._date_of_birth)
print("-----------")
print("Gender : ",self._sex )
print("-----------")
print("Country of birth : ",self._country)
#constructor for the class and assign the variables(eg:firstname)
def __init__(self,firstname,lastname,date_of_birth,sex,country):
self.student_number = random.randint(1,18330751)
self._firstname = firstname
self._lastname = lastname
self._date_of_birth = date_of_birth
self._sex = sex
self._country = country
def get_firstname(self):
return self._firstname
def set_firstname(self,firstname):
self._firstname = firstname
def get_lastname(self):
return self._lastname
def set_lastname(self,lastname):
self._lastname = lastname
def get_date_of_birth(self):
return self._date_of_birth
def set_date_of_birth(self,date_of_birth):
self._date_of_birth = date_of_birth
def get_sex(self):
return self._sex
def set_sex(self,sex):
self._sex = sex
def get_country(self):
return self._country
def set_country(self,country):
self._country = country
#this method for converting object when writing to file and reading the file
def __str__(self):
return f"{firstname,lastname,date_of_birth,sex,country}"
student = []
while True:
print("1. Enter 1 and you are going Write the contents of the student array to a file")
print("-----------")
print("2.Read student data from a file and populate the student array.")
print("-----------")
print("3.Add a new student")
print("-----------")
print("4. Enter 4 and you are going to see all students information")
print("-----------")
print("5. Enter 5 and you are going to write born year to find students who born in this year")
print("-----------")
print("6. Enter 6 and you are going to modify a student record by typing student number because you can't change student number")
print("-----------")
print("7. Enter 7 and you are going to write student number to delete student")
print("-----------")
print("8. Enter 8 and exit the program")
print("-----------")
print("You can choose what to do")
option = int(input("Please write your option: "))
print("-----------")
if option == 1:
f = open("cmse318.txt","w")
for data in student:
f.write(data)
print("-----------")
print("Successfully write to a file!!")
print("-----------")
break
f.close()
if option == 2:
f = open("cmse318.txt","r")
for ln in f:
firstname,lastname,date_of_birth,sex,country = ln.split(",")
s = Student(firstname,lastname,date_of_birth,sex,country)
student.append(s)
print(s)
f.close()
if option == 3:
firstname,lastname,date_of_birth,sex,country = map(str,input("Please Enter student details like this(cemal,göymen,2000,male,cyprus) : ").split(","))
s = Student(firstname,lastname,date_of_birth,sex,country)
student.append(s)
print("-----------")
print('Student created successfully!!')
print("-----------")
print("-----------")
if option == 4 :
for st in student:
st.student_details()
print("-----------")
print("For now these are the students")
print("-----------")
if option == 5:
year1 = int(input("Enter year to show students who born in this year(eg:2000): "))
for dob in student:
if (int(dob.get_date_of_birth()) == year1):
dob.student_details()
print("-----------")
print("All students who born in ", year1)
print("-----------")
if option == 6:
snr = int(input("Enter a student number: "))
for sn in student:
if sn.student_number == snr:
firstname,lastname,date_of_birth,sex,country = map(str,input("Please Enter student details like this(cemal,göymen,2000,male,cyprus) :").split(","))
sn.set_firstname(firstname)
sn.set_lastname(lastname)
sn.set_date_of_birth(date_of_birth)
sn.set_sex(sex)
sn.set_country(country)
print("-----------")
print("Student modify success")
print("-----------")
if option == 7:
snr = int(input("Enter the student number to be deleted : "))
for sn in student:
if sn.student_number == snr:
temp = sn
student.remove(temp)
print("-----------")
print("Student deleted successfully")
print("-----------")
if option == 8:
break
I need help in option 1 and option 2 about reading and writing file. In the reading file it does not read all students from a file it reads just one student and ıf there is more than one student in the file it gives an error. In the writing to file part, the problem is I cannot write the student array to file it just write the last element from the student array but I need all elements from my student array.
Code can be improved as follows.
import random
class Student:
def __init__(self,firstname,lastname,date_of_birth,sex,country,student_number = None):
# reuse student number when we read from file (i.e. if specified)
# set new one if we don't have one
self.student_number = student_number or random.randint(1,18330751) # or causes use of rand value
# if student_number = None
self._firstname = firstname
self._lastname = lastname
self._date_of_birth = date_of_birth
self._sex = sex
self._country = country
def student_details(self):
return (f"Student number : {self.get_student_number()}\n"
f"----------- First Name : {self.get_firstname()}\n"
f"----------- Last Name : {self.get_lastname()}\n"
f"----------- Date Of Birth : {self.get_date_of_birth()}\n"
f"----------- Gender : {self.get_sex()}\n"
f"----------- Country of birth : {self.get_country()}")
def get_firstname(self):
return self._firstname
def set_firstname(self,firstname):
self._firstname = firstname
def get_lastname(self):
return self._lastname
def set_lastname(self,lastname):
self._lastname = lastname
def get_date_of_birth(self):
return self._date_of_birth
def set_date_of_birth(self,date_of_birth):
self._date_of_birth = date_of_birth
def get_sex(self):
return self._sex
def set_sex(self,sex):
self._sex = sex
def get_country(self):
return self._country
def set_country(self,country):
self._country = country
def get_student_number(self):
return self.student_number
def __str__(self):
' For serializing attributes to string --useful for writing to file '
return (f"{self.get_student_number()},"
f"{self.get_firstname()},"
f"{self.get_lastname()},"
f"{self.get_date_of_birth()},"
f"{self.get_sex()},"
f"{self.get_country()}")
def get_student_info():
' Use helper function to ensure student entry has correct number of fields '
while True:
while True:
entry = input('''Please Enter student details comma delimited like this (firstname,lastname,date of birth,gender,country)
Example Emal,Göymen,4/15/2000,Male,Cyprus : ''')
fields = entry.split(',')
if len(fields) == 5:
# Correct number of fields
return fields
else:
print(f'Entry {entry} incorrecst format')
print('Shoulbe be five comma delimitede fields i.e. firstname,lastname,date of birth,gender,country')
students = []
while True:
print('''
1. Write the contents of the student array to a file
-----------
2. Read student data from a file and populate the student array.
-----------
3. Add a new student
-----------
4. Display all students information
-----------
5. Information for students born in a particular year
-----------
6. Modify student record (you need to know student number)
-----------
7. Delete a student (you need to know student number)
-----------
8. Exit program
-----------
Enter option''')
option = int(input("Please write your option: "))
print("-----------")
if option == 1:
with open("cmse318.txt", "w") as f:
for st in students:
f.write(str(st) + '\n')
print("-----------\nSuccessfully wrote to a file!!\n-----------")
if option == 2:
with open("cmse318.txt","r") as f:
students = [] # Start new student array
for ln in f:
student_number,firstname,lastname,date_of_birth,sex,country = ln.rstrip().split(",") # rstrip remove '\n' at end of line
student_number = int(student_number)
s = Student(firstname,lastname,date_of_birth,sex,country,student_number)
students.append(s)
print(str(s))
if option == 3:
firstname,lastname,date_of_birth,sex,country = get_student_info()
s = Student(firstname,lastname,date_of_birth,sex,country)
students.append(s)
print('''-----------
Student created successfully!!
-----------
-----------''')
if option == 4 :
print('''-----------
For now these are the students
-----------
-----------''')
for st in students:
print(st.student_details())
if option == 5:
birth_year = input("Enter year to show students who born in this year(eg:2000): ")
print("-----------"
f"All students who born in {birth_year}"
"-----------")
for st in students:
if birth_year in st.get_date_of_birth(): # e.g. birth_year = 2000, date_of_birth = "May 5, 2000" we get a match
print(st.student_details())
if option == 6:
snr = int(input("Enter a student number: "))
for sn in students:
if sn.student_number == snr:
firstname,lastname,date_of_birth,sex,country = get_student_info()
sn.set_firstname(firstname)
sn.set_lastname(lastname)
sn.set_date_of_birth(date_of_birth)
sn.set_sex(sex)
sn.set_country(country)
print("-----------\nStudent modify success\n-----------")
break
else:
print(f"Student number {snr} not found!!!")
if option == 7:
snr = int(input("Enter the student number to be deleted : "))
# Normally bad practice to delete elements in list while iterating over it,
# but in this case we are only deleting a single element so okay
for sn in students:
if sn.student_number == snr:
students.remove(sn)
print(f"-----------\nStudent {snr} deleted successfully")
break
else:
print("Student {snr} not found")
if option == 8:
print('Exiting')
break

How do I copy an employee information from one dictionary to another?

I am using the Python class Employee to copy create employees in an employee management system and pickle to a file. I got that to work fine, but my instructor wants to be able to search the system even for deleted employees. My question is how do I copy an object from employeDictionary to deletedemployeeDictionary? I keep running into errors.
Here is my employee class:
class Employee:
# Initialize Employee object
def __init__(self, name, ID, department, job):
self.__ID = ID
self.__name = name
self.__department = department
self.__job = job
# Set each object
def set_name(self, name):
self.__name = name
def set_ID(self, ID):
self.__ID = ID
def set_dept(self, department):
self.__department = department
def set_job(self, job):
self.__job = job
# Get each object
def get_name(self):
return self.name
def get_ID(self):
return self.__ID
def get_department(self):
return self.__department
def get_job(self):
return self.__job
def __str__(self):
return (f"ID Number: {self.__ID}\nName: {self.__name}\n"
f"Department: {self.__department}\n Job Title: {self.__job}")
Here is my main code:
import pickle
import emp2
def main():
# Try to open the existing dictionary file
try:
inputFile1 = open('employee.pickle', 'rb')
employeeDictionary = pickle.load(inputFile1)
inputFile1.close()
inputFile2 = open('deletedEmployee.pickle', 'rb')
deletedEmployeeDictionary = pickle.load(inputFile2)
inputFile2.close()
except:
employeeDictionary = {}
deletedEmployeeDictionary = {}
# While loop to continue until user chooses to quit
proceed = True
while proceed:
# Display user's option menu and ask for a choice
print('\n Employee Management System\n')
print('\t1. Lookup an employee')
print('\t2. Add a new employee')
print('\t3. Change an existing employee')
print('\t4. Delete an existing employee')
print('\t5. Save and Quit\n')
choice = int(input('Enter an option to continue: '))
if choice == 1:
lookup (employeeDictionary, deletedEmployeeDictionary)
elif choice ==2:
add(employeeDictionary)
elif choice == 3:
change (employeeDictionary)
elif choice == 4:
delete (employeeDictionary, deletedEmployeeDictionary)
elif choice == 5:
save_quit(employeeDictionary, deletedEmployeeDictionary)
proceed = False
else:
print ('Invalid input!')
choice = int(input('Enter an option to continue: '))
# Lookup an employee
def lookup(dictionary, dictionary2):
# Look up the ID number if it is in the dictionary
employee_id = int(input('Enter the employee ID number: '))
if employee_id in dictionary:
# print('employee_id', ': ', dictionary[employee_id])
print(dictionary.get(employee_id))
elif employee_id in dictionary2:
# print('employee_id', ': ', dictionary2[employee_id])
print(dictionary2.get(employee_id))
else:
print("That ID number was not found.")
# Add an employee
def add(dictionary):
# Add a new employee
empyloyee_id = int(input('Enter the employee ID number: '))
if empyloyee_id not in dictionary.keys():
name = input('Enter the name of the employee: ')
dept = input('Enter the employee department: ')
job = input('Enter the employee job title: ')
entry = emp2.Employee(name, empyloyee_id, dept, job)
dictionary[empyloyee_id] = entry
print('Employee added succesfully')
else:
print('Employee already exists!')
# Change an employee
def change(dictionary):
# If user-entered ID is in dictionary, allow them to change the info
employee_id = int(input(
'Enter the employee ID you would like to change: '))
if employee_id in dictionary.keys():
name = input('Enter new employee name: ')
dept = input('Enter new employee department: ')
job = input('Enter new employee job title: ')
entry = emp2.Employee(name, employee_id, dept, job)
dictionary[employee_id] = entry
print('Employee changed successfully.')
else:
print('That employee ID was not found.')
# Delete an employee
def delete(dictionary, dictionary2):
# If user-entered ID is in dictionary, delete the entry
employee_id = int(input(
'Enter the employee ID you would like to remove: '))
if employee_id in dictionary.keys():
entry = emp2.Employee(dictionary[employee_id])
dictionary2[empyloyee_id] = entry
del dictionary[employee_id]
print('Employee successfully moved to deleted directory!')
else:
print('That employee ID was not found.')
# Save the dictionary and quit the program
def save_quit(dictionary, dictionary2):
# Pickle the dictionary and save to a file
outputFile1 = open('employee.pickle', 'wb')
pickle.dump(dictionary, outputFile1)
outputFile1.close
# Pickle the dictionary and save to a file
outputFile2 = open('deletedEmployee.pickle', 'wb')
pickle.dump(dictionary2, outputFile2)
outputFile2.close
def move(dictionary, dictionary2, employee_id):
empyloyee_id = dictionary.get(employee_id)
name = dictionary.get(name)
dept = dictionary.get(department)
job = dictionary.get(job)
entry = emp2.Employee(name, empyloyee_id, dept, job)
dictionary2[empyloyee_id] = entry
#Calls main function.
if __name__== '__main__':
main()
You have several pieces that require update.
In your lookup function, you do not inform the user whether or not the employee is in the active list or deleted list. You might want to let them know.
I moved your MOVE function to above the delete function. since your DELETE function requires a move call, having MOVE above DELETE gives the ability to handle the function once.
In your DELETE, we updated the script to allow for MOVE to happen, then we can use the POP function to remove the object from the roster.
import pickle
import employee as emp2
def main():
# Try to open the existing dictionary file
try:
inputFile1 = open('employee.pickle', 'rb')
employeeDictionary = pickle.load(inputFile1)
inputFile1.close()
inputFile2 = open('deletedEmployee.pickle', 'rb')
deletedEmployeeDictionary = pickle.load(inputFile2)
inputFile2.close()
except:
employeeDictionary = {}
deletedEmployeeDictionary = {}
# While loop to continue until user chooses to quit
proceed = True
while proceed:
# Display user's option menu and ask for a choice
print('\n Employee Management System\n')
print('\t1. Lookup an employee')
print('\t2. Add a new employee')
print('\t3. Change an existing employee')
print('\t4. Delete an existing employee')
print('\t5. Save and Quit\n')
choice = int(input('Enter an option to continue: '))
if choice == 1:
lookup(employeeDictionary, deletedEmployeeDictionary)
elif choice == 2:
add(employeeDictionary)
elif choice == 3:
change(employeeDictionary)
elif choice == 4:
delete(employeeDictionary, deletedEmployeeDictionary)
elif choice == 5:
save_quit(employeeDictionary, deletedEmployeeDictionary)
proceed = False
else:
print('Invalid input!')
choice = int(input('Enter an option to continue: '))
# Lookup an employee
def lookup(dictionary, dictionary2):
# Look up the ID number if it is in the dictionary
employee_id = int(input('Enter the employee ID number: '))
if employee_id in dictionary:
# print('employee_id', ': ', dictionary[employee_id])
print('Active Record...')
print(dictionary.get(employee_id))
elif employee_id in dictionary2:
# print('employee_id', ': ', dictionary2[employee_id])
print("Deleted Record...")
print(dictionary2.get(employee_id))
else:
print("That ID number was not found.")
# Add an employee
def add(dictionary):
# Add a new employee
empyloyee_id = int(input('Enter the employee ID number: '))
if empyloyee_id not in dictionary.keys():
name = input('Enter the name of the employee: ')
dept = input('Enter the employee department: ')
job = input('Enter the employee job title: ')
entry = emp2.Employee(name, empyloyee_id, dept, job)
dictionary[empyloyee_id] = entry
print('Employee added succesfully')
else:
print('Employee already exists!')
# Change an employee
def change(dictionary):
# If user-entered ID is in dictionary, allow them to change the info
employee_id = int(input(
'Enter the employee ID you would like to change: '))
if employee_id in dictionary.keys():
name = input('Enter new employee name: ')
dept = input('Enter new employee department: ')
job = input('Enter new employee job title: ')
entry = emp2.Employee(name, employee_id, dept, job)
dictionary[employee_id] = entry
print('Employee changed successfully.')
else:
print('That employee ID was not found.')
def move(dictionary, dictionary2, employee_id):
dictionary2[employee_id] = dictionary.get(employee_id)
# Delete an employee
def delete(dictionary, dictionary2):
# If user-entered ID is in dictionary, delete the entry
employee_id = int(input(
'Enter the employee ID you would like to remove: '))
if employee_Id in dictionary:
move(dictionary, dictionary2, employee_id)
dictionary.pop(employee_id)
print('Employee successfully moved to deleted directory!')
else:
print('Employee not in directory!')
# Save the dictionary and quit the program
def save_quit(dictionary, dictionary2):
# Pickle the dictionary and save to a file
outputFile1 = open('employee.pickle', 'wb')
pickle.dump(dictionary, outputFile1)
outputFile1.close
# Pickle the dictionary and save to a file
outputFile2 = open('deletedEmployee.pickle', 'wb')
pickle.dump(dictionary2, outputFile2)
outputFile2.close
# Calls main function.
if __name__ == '__main__':
main()

Proper use of class and dict from user input

I've been struggling with my code for a class project and am in need of some help. I am not sure if I need to have a nested dictionary or list of dict or just use class in a list or dict. I've struggled to find the answers and could use some help with my code.
Should I just use list instead or am I thinking of this the right way, having the values stored in a dictionary or nested dict of some kind.
I'm especially at a loss for menu==3 #delete an item because as it is now I can only delete one attribute but what I need is to delete a whole property by property ID if possible
As you can probably tell I'm quite confused by now and would really appreciate any help from more experienced programmers.
inventory = {}
#class & constructor
class Property:
def __init__(self, propertyID, address, city, state, zipcode, squarefeet, modelname, salestatus):
self.propertyID = propertyID
self.address = address
self.city = city
self.state = state
self.zipcode = zipcode
self.modelname = modelname
self.squarefeet = squarefeet + 'Square Feet'
self.salestatus = salestatus
def print_Property(o):
if not isinstance(o, Property):
raise TypeError('print_Property(): requires a Property')
print('The property selected is Property ID: {} located at {} {} {} The Sqare footage is {}, {} model, Current status: {}'. format(o.propertyID,o.addresss, o.city, o.state, o.zipcode, o.squarefeet, o.modelname, o.salestatus))
def main():
print('What would you like to do today?')
print('----------------------------------------')
print('1. Add a new item to the Inventory')
print('2. Update an Existing item in the Inventory')
print('3. Delete an existing item from the Inventory')
print('4. View the current item inventory')
print('5. Print the Inventory to a text file')
print('------------------------------')
while True:
try:
menu = int(input('Type a number 1-5'))
if menu == 1: #Add data
print('Add a new property to the inventory...')
propertyID = input('Enter the property Listing ID:') #User inputting a property ID
inventory['Property ID']= propertyID
address = input('Enter the property address:') #User inputting an address
inventory['Address']= address
city = input('Enter property city:') #User inputting a city
inventory['City']= city
state = input('Enter property state:') #User inputting a state
inventory['State']= state
zipcode = int(input('Enter the property zipcode:')) #User inputting a zipcode
inventory['Zipcode']= zipcode
modelname = input('Enter property model name:') #User inputting a property model name
inventory['Model Name']= modelname
squarefeet = int(input('Enter the sqaure footage of the property:')) #User inputting the sqaure footage for the property
inventory['Square Footage']= squarefeet
salestatus = input('Enter the property status:(Is the home sold, available, or under contract?):') #User inputting the property status
inventory['Current Staus']= salestatus
print('The following properties are in the inventory now:')
print(inventory)
#break
elif menu == 2: #Update data
print('Update an item from the inventory...')
print (inventory)
itemreplace = input("Enter the name of the attribute you wish to replace:")
itemupdate = input("Enter the new information for that attribute now:")
inventory[itemreplace]= itemupdate
print(inventory)
elif menu == 3: #Delete data
print("Which property do you want to delete?")
print(inventory)
itemdel = input("Enter the Property ID of the property to delete.")
if itemdel in inventory:
del inventory[itemdel]
print(inventory)
elif menu == 4: #View data
print(inventory)
elif menu == 5: #Print data
output = open("PropertyData.txt", "w")
for item in inventory:
output.write("%s\n" % item)
print('Text file \'PropertyData.txt\' has been created.')
else:
print('That number is not valid. Please try 1-5.')
except ValueError: #throw an error for anything that is not a number
print('You may only select values 1-5. (ex.: 2)')
if __name__ == '__main__': main()
#Lucas is right. Here is a fully working ( I think :) ) system:
import json
class Property:
def __init__(self, propertyID, address, city, state, zipcode, squarefeet, modelname, salestatus):
self.propertyID = propertyID
self.address = address
self.city = city
self.state = state
self.zipcode = zipcode
self.modelname = modelname
self.squarefeet = squarefeet
self._sqfeet_description = str(squarefeet) + ' Square Feet'
self.salestatus = salestatus
def __str__(self):
o = self
return 'Property ID: {}. Address: {}, {}, {}, {}. Size: {} sq feet, {} model. Status: {}.'.format(o.propertyID,o.address, o.city, o.state, o.zipcode, o.squarefeet, o.modelname, o.salestatus)
def as_json(self):
return {x:y for x,y in self.__dict__.items() if not x.startswith("_")}
def int_input(prompt, range=None):
while True:
ans = input(prompt)
if not ans.isnumeric():
print("Please enter a valid number")
continue
ans = int(ans)
if range == None:
return ans
if ans not in range:
print(f"Please enter a number between {min(range)} and {max(range)}")
continue
return ans
inventory = []
def main():
print('What would you like to do today?')
print('----------------------------------------')
print('1. Add a new item to the Inventory')
print('2. Update an Existing item in the Inventory')
print('3. Delete an existing item from the Inventory')
print('4. View the current item inventory')
print('5. Print the Inventory to a text file')
print('------------------------------')
while True:
menu = int_input("Choose an option 1-5", range(1,6))
if menu == 1:
# add data
propertyID = input('Enter the property Listing ID:') #User inputting a property ID
address = input('Enter the property address:') #User inputting an address
city = input('Enter property city:') #User inputting a city
state = input('Enter property state:') #User inputting a state
zipcode = int_input('Enter the property zipcode:') #User inputting a zipcode
modelname = input('Enter property model name:') #User inputting a property model name
squarefeet = int_input('Enter the sqaure footage of the property:') #User inputting the sqaure footage for the property
salestatus = input('Enter the property status:(Is the home sold, available, or under contract?):') #User inputting the property status
this_property = Property(
propertyID,
address,
city,
state,
zipcode,
squarefeet,
modelname,
salestatus)
inventory.append(this_property)
print('The following properties are in the inventory now:')
print(*("\t" + str(i) for i in inventory), sep="\n")
print()
elif menu == 2:
# update data
while True:
propertyID = input("Enter the property id: ")
this_property = [x for x in inventory if x.propertyID == propertyID]
if not this_property:
print("That property doesn't exist")
continue
this_property = this_property[0]
break
lookup = {
"propertyID": str,
"address":str,
"city":str,
"state":str,
"zipcode":int,
"modelname":str,
"squarefeet":int,
"salestatus":str
}
while True:
detail_name = input("Enter the detail you wish to change")
if detail_name not in lookup:
print("That detail does not exist")
continue
break
if lookup[detail_name] == int:
new = int_input("Enter the new value:")
else:
new = input("Enter the new value:")
setattr(this_property, detail_name, new)
elif menu == 3:
# delete
while True:
propertyID = input("Enter the property id: ")
this_property = [i for i, x in enumerate(inventory) if x.propertyID == propertyID]
if not this_property:
print("That property doesn't exist")
continue
this_property = this_property[0]
break
del inventory[this_property]
elif menu == 4:
# print inventory
print('The following properties are in the inventory now:')
print(*("\t" + str(i) for i in inventory), sep="\n")
print()
elif menu == 5:
# save
new_inv = [x.as_json() for x in inventory]
with open("output.txt", "w") as f:
json.dump(new_inv, f)
if __name__ == '__main__':
main()
If you want to save your properties and be able to load them again, add this method to Property:
class Property:
...
#classmethod
def from_json(cls, json_code):
c = cls(*(None for _ in range(8)))
for x,y in json_code.items():
setattr(c, x, y)
return c
and this function to the body of your program:
def load_from_file():
with open("output.txt") as f:
for item in json.load(f):
inventory.append(Property.from_json(item))
and then call the function at the start:
if __name__ == '__main__':
load_from_file()
main()
(obviously make sure the file exists before that though - just save [] to output.txt before running the program for the first time)
The easiest solution is to use a list of Property objects, where each element in a list is an individual property. Adding properties to the inventory means creating a new object, filling in all the fields and appending it to the inventory list.

Name Error on a class method previously defined and IndexError on an Index that should exist

so, I'm getting a NameError on npc.name(and I imagine it will arise in all subsequent class method-linked variables I'm trying to redefine), also, I have an IndexError arising earlier.
I'll explain in more detail,but first, my code.
This is my full code, beware:
# import pickle
import pickle
npcs_pickle_file = 'NPCatt.pk'
npc_count = 200
class NPC:
def __init__(self, name="", occupation="", weakness="", need="", desire="", enemy="",
rumor="", secret="", passion="", redeeming_quality="",damning_quality="", happy="",
occ_desire="", occ_complication="", pc_opinion="", accomplishment="", magical_gear="",
political_influence="", resource="", intel="", research=""):
# Attributes
self.name = name
self.occupation = occupation
self.weakness = weakness
self.need = need
self.desire = desire
self.enemy = enemy
self.rumor = rumor
self.secret = secret
self.passion = passion
self.redeeming_quality = redeeming_quality
self.damning_quality=damning_quality
self.happy = happy
self.occ_desire = occ_desire
self.occ_complication = occ_complication
self.pc_opinion = pc_opinion
self.accomplishment = accomplishment
self.magical_gear = magical_gear
self.political_influence = political_influence
self.resource = resource
self.intel = intel
self.research = research
def __str__(self):
npc_output = "####NPC SUMMARY####\n"
for att, val in self.__dict__.items():
if val:
npc_output += (f"{att} = {val}\n")
return npc_output
# open a pickle file
# load your data back to memory when you need it
try:
with open(npcs_pickle_file, 'rb') as fi:
npcs = pickle.load(fi)
except FileNotFoundError as fne:
#file doesnt exist prob first time running so create a dict with the 170 npc id's
npcs = {id: None for id in range(npc_count)}
#select an NPC to modify / create
npc_id = None
while not npc_id:
try:
npc_id = int(input(f"Enter the id number of the NPC you wish to modify: "))
except ValueError as ve:
print("You must provide a numerical id")
if npc_id < 0 or npc_id >= npc_count:
npc_id = None
print(f"you must provide a value between 0 and {npc_count}")
if npcs[npc_id]:
npc = npcs[npc_id]
print(npc)
modify = input("This NPC already exists, do you want to continue and change them? (y/n): ")
if modify.lower() == "y":
name = input("Enter name of NPC: ")
occupation = input("Enter NPC occupation: ")
weakness= input("Enter Weakness: ")
need= input("Enter Need: ")
desire= input("Enter Desire: ")
enemy= input("Enter Enemy: ")
rumor= input("Enter Rumor: ")
secret= input("Enter Secret: ")
passion= input("Enter Passion: ")
redeeming_quality=input("Enter Redeeming Quality: ")
damning_quality=input("Enter Damning Quality: ")
happy= input("Enter, is this NPC happy?: ")
occ_desire= input("Enter an Occupational Desire: ")
occ_complication= input("Enter an Occupational Complication: ")
pc_opinion= input("Enter this NPC's disposition toward the PCs: ")
accomplishment= input("Enter an Accomplishment: ")
magical_gear= input("Enter Magical Gear: ")
political_influence=input("Enter Political Influence: ")
resource= input("Enter Resource Level: ")
intel= input("Enter Intel Tier: ")
research= input("Enter Research: ")
npc.name = name
npc.occupation = occupation
npc.weakness = weakness
npc.need = need
npc.desire= desire
npc.enemy= enemy
npc.rumor= rumor
npc.secret= secret
npc.passion= passion
npc.redeeming_quality= redeeming_quality
npc.damning_quality= damning_quality
npc.happy= happy
npc.occ_desire=occ_desire
npc.occ_complication=occ_complication
npc.pc_opinion=pc_opinion
npc.accomplishment=accomplishment
npc.magical_gear=magical_gear
npc.political_influence=political_influence
npc.resource=resource
npc.intel=intel
npc.research=research
else:
npcs[npc_id] = NPC(name=npc.name, occupation=npc.occupation,weakness=npc.weakness,need=npc.need,desire=npc.desire,\
enemy=npc.enemy,rumor=npc.rumor,secret=npc.secret,passion=npc.passion,redeeming_quality=npc.redeeming_quality,\
damning_quality=npc.damning_quality,happy=npc.happy,occ_desire=npc.occ_desire,\
occ_complication=npc.occ_complication\
,pc_opinion=npc.pc_opinion,accomplishment=npc.accomplishment,\
magical_gear=npc.magical_gear,political_influence=npc.political_influence,resource=npc.resource,\
intel=npc.intel,research=npc.research)
else:
name = input("Enter name of NPC: ")
occupation = input("Enter NPC occupation: ")
weakness= input("Enter Weakness: ")
need= input("Enter Need: ")
desire= input("Enter Desire: ")
enemy= input("Enter Enemy: ")
rumor= input("Enter Rumor: ")
secret= input("Enter Secret: ")
passion= input("Enter Passion: ")
redeeming_quality=input("Enter Redeeming Quality: ")
damning_quality=input("Enter Damning Quality: ")
happy= input("Enter, is this NPC happy?: ")
occ_desire= input("Enter an Occupational Desire: ")
occ_complication= input("Enter an Occupational Complication: ")
pc_opinion= input("Enter this NPC's disposition toward the PCs: ")
accomplishment= input("Enter an Accomplishment: ")
magical_gear= input("Enter Magical Gear: ")
political_influence=input("Enter Political Influence: ")
resource= input("Enter Resource Level: ")
intel= input("Enter Intel Tier: ")
research= input("Enter Research: ")
npc.name = name
npc.occupation = occupation
npc.weakness = weakness
npc.need = need
npc.desire= desire
npc.enemy= enemy
npc.rumor= rumor
npc.secret= secret
npc.passion= passion
npc.redeeming_quality= redeeming_quality
npc.damning_quality= damning_quality
npc.happy= happy
npc.occ_desire=occ_desire
npc.occ_complication=occ_complication
npc.pc_opinion=pc_opinion
npc.accomplishment=accomplishment
npc.magical_gear=magical_gear
npc.political_influence=political_influence
npc.resource=resource
npc.intel=intel
npc.research=research
with open(npcs_pickle_file, 'wb') as fi:
# dump your data into the file
pickle.dump(npcs, fi)
I'm a noob so the code structure was provided as an answer on my only other question so far on the site. I've expanded it for my purposes.
The thing is, the NPC indexed as [1], has been stored perfectly, shows up as needed, and is modifiable.
But when defining new NPCs, I get first an IndexError for new Indexable NPCs, which I caught with a
try: #the code for when the NPC has been previously defined
except IndexError:#the code on the last else block, for new indexes
in order to check whether the rest of the code worked,
and a NameError arises on the last else block where I define each attribute as
self.att=att
now, my best guess is that it has to do with local vs global variable definitions, but I have no idea how to solve either error.
Thank you if you read all the way through, and I'm sorry.
Please help, if you can and want to.
Your IndexError issue comes from unpickling a file created by the previous version of your script. If this file contains valuable data, just rename it for the moment, and once you'll get you script working and stable enough, it will be time to write a migration script to get your old data back. Else, well, just ditch it xD
wrt/ the NameError, it's in the last else block: you are trying to set attributes on a npc variable that is indeed not defined at this point - it's only defined in the if block:
if npcs[npc_id]:
npc = npcs[npc_id]
# way too much code here
else:
# repeated code here
# and here's the issue:
npc.something = something
You already noticed that "mashing together pieces of code without understanding them doesn't always work", which is a good start (at least you're aware of it, so there's still hope xD), now here's another enlightenment for you: "trying to understand messy code is hard". That's why good code structure is important. Also, short functions that only (or mostly) depend on their arguments are easier to understand (and test !) than long scripts with lots of conditionals and code blocks that depends on some variable being (or not) defined some 20+ lines away.
I usually don't do this, but it seems that in this case, you may benefit from seeing what a decently structured code looks like. It's far from perfect and could benefit from some improvements (like, when editing an existing npc, letting the user specify which attributes he wants to change instead of asking them to retype everything) but well, that's your job, not mine ;-)
import pickle
# coding conventions: pseudo-constants should be ALL_UPPER
NPCS_PICKLE_FILE = 'NPCatt.pk'
NPC_COUNT = 200
# coding convention: class names should be CamelCase
class Npc:
def __init__(self, name="", occupation="", weakness="", need="", desire="", enemy="",
rumor="", secret="", passion="", redeeming_quality="",damning_quality="", happy="",
occ_desire="", occ_complication="", pc_opinion="", accomplishment="", magical_gear="",
political_influence="", resource="", intel="", research=""):
# Attributes
self.name = name
self.occupation = occupation
self.weakness = weakness
self.need = need
self.desire = desire
self.enemy = enemy
self.rumor = rumor
self.secret = secret
self.passion = passion
self.redeeming_quality = redeeming_quality
self.damning_quality = damning_quality
self.happy = happy
self.occ_desire = occ_desire
self.occ_complication = occ_complication
self.pc_opinion = pc_opinion
self.accomplishment = accomplishment
self.magical_gear = magical_gear
self.political_influence = political_influence
self.resource = resource
self.intel = intel
self.research = research
def update(self, **values):
for key, val in values.items():
# make sure we're only accepted known attributes
if not hasattr(self, key):
raise AttributeError("Npc object has no attribute '{}'".format(key))
setattr(self, key, val)
def __str__(self):
# in Python, string concatenation is better done by
# building a list and joining it afterward
npc_output = ["####NPC SUMMARY####"]
for att, val in self.__dict__.items():
if val:
npc_output.append(f"{att} = {val}")
npc_output.append("") # so we have a last newline
return "\n".join(npc_output)
class InvalidDataFile(ValueError):
pass
def load_npcs_from_file():
with open(NPCS_PICKLE_FILE, 'rb') as fi:
try:
npcs = pickle.load(fi)
except EOFError as e:
raise InvalidDataFile(
"looks like {} is empy - expected a dict, got {}".format(NPCS_PICKLE_FILE, e)
)
# make sure we don't have incorrect data from
# the previous version where what was pickled was a list
if not isinstance(npcs, dict):
raise InvalidDataFile(
"looks like {} is obsolete or corrupted - expected a dict, got {}".format(NPCS_PICKLE_FILE, ncps)
)
# make sure we ALWAYS have `NPC_COUNT` npcs whatever
# (ie: in case the pickle didn't have as many entries as expected)
missing = NPC_COUNT - len(npcs)
if missing > 0:
for id in range(NPC_COUNT):
ncps.setdefault(id, None)
return npcs
def init_npcs():
return {id: None for id in range(NPC_COUNT)}
def load_npcs():
try:
return load_npcs_from_file()
except (FileNotFoundError, InvalidDataFile) as e:
# so you know what's happening...
print("got {} when trying to load npcs from file - creating a new dataset".format(e))
return init_npcs()
def save_npcs(npcs):
with open(NPCS_PICKLE_FILE, 'wb') as fi:
# dump your data into the file
pickle.dump(npcs, fi)
def get_npc_values():
# factor out common stuff
# XXX you definitly want to validate user inputs
values = {}
values["name"] = input("Enter name of NPC: ")
values["occupation"] = input("Enter NPC occupation: ")
values["weakness"] = input("Enter Weakness: ")
values["need"] = input("Enter Need: ")
values["desire"] = input("Enter Desire: ")
values["enemy"] = input("Enter Enemy: ")
values["rumor"] = input("Enter Rumor: ")
values["secret"] = input("Enter Secret: ")
values["passion"] = input("Enter Passion: ")
values["redeeming_quality"] = input("Enter Redeeming Quality: ")
values["damning_quality"] = input("Enter Damning Quality: ")
values["happy"] = input("Enter, is this NPC happy?: ")
values["occ_desire"] = input("Enter an Occupational Desire: ")
values["occ_complication"] = input("Enter an Occupational Complication: ")
values["pc_opinion"] = input("Enter this NPC's disposition toward the PCs: ")
values["accomplishment"] = input("Enter an Accomplishment: ")
values["magical_gear"] = input("Enter Magical Gear: ")
values["political_influence"] = input("Enter Political Influence: ")
values["resource"] = input("Enter Resource Level: ")
values["intel"] = input("Enter Intel Tier: ")
values["research"] = input("Enter Research: ")
return values
def update_npc(npc):
new_values = get_npc_values()
npc.update(**new_values)
def create_npc():
values = get_npc_values()
return Npc(**values)
def get_npc_id():
#select an NPC to modify / create
npc_id = None
while npc_id is None:
try:
npc_id = int(input(f"Enter the id number of the NPC you wish to modify: "))
except ValueError as ve:
print("You must provide a numerical id")
if npc_id < 0 or npc_id >= NPC_COUNT:
npc_id = None
print(f"you must provide a value between 0 and {NPC_COUNT}")
return npc_id
def edit_npc(npcs):
npc_id = get_npc_id()
# this should be safe now... theoretically at least
npc = npcs[npc_id]
if npc is None:
ok = input("This NPC doesn't exist yet, do you want to create it (y/n): ")
if ok.strip().lower() == 'y':
npcs[npc_id] = create_npc()
# let the caller know something was changed
return True
else:
ok = input("This NPC already exists, do you want to continue and change them? (y/n): ")
if ok.strip().lower() == "y":
update_npc(npc)
# let the caller know something was changed
return True
# let the caller know nothing was changed
return False
def show_npcs(npcs):
for id, npc in npcs.items():
print("{} : {}".format(id, npc))
print("") # add a blank line
def get_next_action():
while True:
print("what do you want to do ?")
print("S - show existing npcs")
print("E - edit a npc")
print("Q - quit")
action = input(">> ").strip().upper()
if action not in "SEQ":
print("sorry, I don't undertand '{}'".format(action))
return action
def main():
npcs = load_npcs()
while True:
nb_valids = len([_ for _ in npcs.values() if _])
print("we have {} valid npcs".format(nb_valids))
action = get_next_action()
if action == "Q":
break
elif action == "E":
if edit_npc(npcs):
print("saving data")
save_npcs(npcs)
elif action == "S":
show_npcs(npcs)
if __name__ == "__main__":
main()

ValueError: not enough values to unpack (expected 3, got 2) & TypeError: must be str, not MemberClass

Below is my code for a class I am currently working. The title contains the errors I am receiving. Could someone please assist with my code? (The comment's explain the area of concern. Main Menu functions 5 & 6.)
PART 1 - CLASS ESTABLISHMENT
class MemberClass:
name = ""
phone = 0
number = 0
# Initiator Method
def __init__(self, name, phone, number):
self.name = name
self.phone = phone
self.number = number
# Mutator Method 1
def set_name(self, name):
self.name = name
# Mutator Method 2
def set_phone(self, phone):
self.phone = phone
# Mutator Method 3
def set_number(self, number):
self.number = number
# Accessor Method 1
def get_name(self):
return self.name
# Accessor Method 2
def get_phone(self):
return self.phone
# Accessor Method 3
def get_number(self):
return self.number
# Display Method
def display_data(self):
print("")
print("Current Team Member's Information")
print("------------------------------------------------")
print("Member's Name: ", self.name)
print("Member's Phone Number: ", self.phone)
print("Member's Jersey Number: ", self.number)
print("------------------------------------------------")
PART 2 - PROGRAM FUNCTIONS AND DATA
# Create a function for the main menu
def print_menu():
print("===========Main Menu===========")
print("1. Display Current Team Roster.")
print("2. Add Member.")
print("3. Remove Member.")
print("4. Edit Member.")
print("5. Save Progress.")
print("6. Load Current Team Roster")
print("9. Exit Program.\n")
return int(input("Please Enter Your Selection: "))
# Create a function for main menu option 1
def print_members(team_members):
if len(team_members) == 0:
print("No Current Team Members In Memory! Please Add All Team Members.")
else:
for x in team_members.keys():
team_members[x].display_data()
# Create a function for main menu option 2
def add_members(team_members):
new_name = input("Enter New Team Member's Name: ")
new_phone = int(input("Enter New Team Member's Phone Number: "))
new_number = int(input("Enter New Team Member's Jersey Number: "))
team_members[new_name] = MemberClass(new_name, new_phone, new_number)
return team_members
# Create a function for main menu option 3
def remove_members(team_members):
remove_name = input("Enter Existing Team Member's Name to Remove: ")
if remove_name in team_members:
del team_members[remove_name]
print("The Team Member ("+remove_name+") Is No Longer In Our Roster.")
else:
print("The Provided Name ("+remove_name+") Is Not Currently In Our Roster. Please Try Again.")
return team_members
# Create a function for main menu option 4
def edit_members(team_members):
original_name = input("Enter Existing Team Member's Name To Edit: ")
if original_name in team_members:
adjusted_name = input("Enter Existing Team Member's Updated Name: ")
adjusted_phone = int(input("Enter Existing Team Member's Updated Phone Number: "))
adjusted_number = int(input("Enter Existing Team Member's Updated Jersey Number: "))
del team_members[original_name]
team_members[original_name] = MemberClass(adjusted_name, adjusted_phone, adjusted_number)
else:
print("The Provided Name ("+original_name+") Is Not Currently In Our Roster. Please Try Again.")
return team_members
# Create a function for main menu option 5 ***PROBLEM AREA***
def save_members(members, filename):
out_file = open(filename, "wt")
with open(filename, "wt") as out_file:
for name, phone, number in members.items():
out_file.write(name + "," + phone + "," + number + "\n")
# Create a function for main menu option 6 ***PROBLEM AREA***
def load_members(members, filename):
in_file = open(filename, "rt")
with open(filename, "rt") as in_file:
while True:
in_line = in_file.readline()
if not in_line:
break
in_line = in_line[:-1]
name, phone, number = in_line.split(",")
members[name] = phone
PART 3 - PROGRAM ROOT CODE
# Team manager welcome screen, date & time
print("Welcome to San Angelo's Softball Team Roster")
print("This program keeps the most up-to-date information")
print("Today's Date: April 23, 2018")
print("Current Time: 0900\n")
# Create a dictionary named "team_members"
team_members = {}
# Provides Menu Screen
menu_selection = print_menu()
# Create while loop repeating the main menu.
while menu_selection != 9:
if menu_selection == 1:
print_members(team_members)
elif menu_selection == 2:
team_members = add_members(team_members)
elif menu_selection == 3:
team_members = remove_members(team_members)
elif menu_selection == 4:
team_members = edit_members(team_members)
elif menu_selection == 5:
filename = input("Enter Desired Filename: ")
save_members(team_members, filename)
elif menu_selection == 6:
filename = input("Enter Existing Filename: ")
load_members(team_members, filename)
menu_selection = print_menu()
print("Thank You For Updating San Angelo's Softball Team Roster!")
When you iterate a dictionary via dict.items, you may only iterate key / value pairs. Therefore, this line will fail as you are attempting to unpack 3 items when only 2 exist (key & value):
for name, phone, number in members.items():
Instead, what you should do:
for name, myclass in members.items():
phone = myclass.phone
number = myclass.number

Categories

Resources