python function Namerror: name 'dictionary' is not defined - python

I would like to load a file and convert it to a dictionary. then, would like to use the loaded file to display the data. user input for choice is between 1 and 2, in order to decide which function to run.
The catch is if I press 2 before 1 then it will display the message "dictionary is empty". Again, when I load the file and try to run display data, it is showing "Nameerror: name 'dictionary' is not defined"
The code is as below: (Thanks in advance)
def load_data():
import csv
open_data = open('file.csv', 'r')
datasets = csv.reader(open_data)
mydict = {row[0]:row[1:] for row in datasets}
return mydict
def display_data(my_dict):
ds = my_dict
if ds == {}:
print("dictionary is empty")
else:
for key, value in ds.items():
print(key)
print(value)
def main():
while True:
choice = int(input("select 1 or 2"))
if choice == 1:
my_dict = load_data()
print(my_dict)
elif choice == 2:
display_data(my_dict)
main()

First of all.The code you provided has many faults.
The key point is you should use a variable my_dict to store the dict you load or display the empty dict if type 2 before 1.
Try the code list below:
import csv
def load_data():
open_data = open('file.csv', 'r')
datasets = csv.reader(open_data)
mydict = {row[0]:row[1:] for row in datasets}
return mydict
def display_data(my_dict):
ds = my_dict
if ds == {}:
print("dictionary is empty")
else:
for key, value in ds.items():
print(key)
print(value)
def main():
my_dict = {}
while True:
choice = int(input("select 1 or 2"))
if choice == 1:
my_dict = load_data()
print(my_dict)
elif choice == 2:
display_data(my_dict)
main()

You have not defined any my_dict in line 24, that is why it is giving a name error.
You shall add the line :
my_dict = {}
If you want your desired output.

In choice 2 you have no data or haven't assigned any value to my_dict before calling display_data you should load those data in my_dict and pass it to the function
Here is the code
def load_data():
import csv
open_data = open('file.csv', 'r')
datasets = csv.reader(open_data)
mydict = {row[0]:row[1:] for row in datasets}
return mydict
def display_data(my_dict):
ds = my_dict
if ds == {}:
print("dictionary is empty")
else:
for key, value in ds.items():
print(key)
print(value)
def main():
while True:
choice = int(input("select 1 or 2"))
if choice == 1:
my_dict = load_data()
print(my_dict)
elif choice == 2:
my_dict = load_data()
display_data(my_dict)
main()

Related

Python dictionary is ordered alphabetically - how do I order it chronologically?

I'm following a tutorial (uploaded oct. 2020) about web scraping and storing the data in a dictionary. Everything works fine except the data in my dictionary starts with the newest entry and ends with the first one.
Should: {title,........, budget}
Is: {budget,........, title}
What could be the resaon for this to happen?
Part of the code:
def get_content_value(row_data):
if row_data.find("li"):
return [li.get_text(" ", strip = True).replace("\xa0", " ") for li in row_data.find_all("li")]
else:
return row_data.get_text(" ", strip = True).replace("\xa0", " ")
movie_info = {}
for index, row in enumerate(info_rows):
if index == 0:
movie_info['title'] = row.find("th").get_text(" ", strip = True)
elif index == 1:
continue
else:
content_key = row.find("th").get_text(" ", strip = True)
content_value = get_content_value(row.find("td"))
movie_info[content_key] = content_value
movie_info
index == 0 is the title
index == 1 is a picture i don't want to have
EDIT:
It's not reversed, it's in alphabetical order! Why? And how can i change it to chronological order?
Dictionaries are inherently not sorted/ordered. This is unlike lists and tuples that are ordered. To get around this issue, the collections library has OrderedDict.
You can use something like this:
# Import the OrderedDict object from `collections`
from collections import OrderedDict
def get_content_value(row_data):
if row_data.find("li"):
return [li.get_text(" ", strip = True).replace("\xa0", " ") for li in row_data.find_all("li")]
else:
return row_data.get_text(" ", strip = True).replace("\xa0", " ")
# Instead of using a regular dictionary ("{}"), we set `movie_info` to be an OrderedDict
movie_info = OrderedDict()
for index, row in enumerate(info_rows):
if index == 0:
movie_info['title'] = row.find("th").get_text(" ", strip = True)
elif index == 1:
continue
else:
content_key = row.find("th").get_text(" ", strip = True)
content_value = get_content_value(row.find("td"))
movie_info[content_key] = content_value
movie_info
It's a bit tricky, but you can do it like below.
from collections import OrderedDict
dictionary = {'one': 1, 'two': 2, 'three':3}
res = OrderedDict(reversed(list(dictionary.items())))

Rewrite the code without using objects in python

When not using objects i am finding it difficult to store and parse through the data. Looking for ways where i can shorten the code using generator comprehension.
for a problem where input to the program code is as below
Courses
TRAN~Transfiguration~1~2011-2012~Minerva McGonagall
CHAR~Charms~1~2011-2012~Filius Flitwick
Students
SLY2301~Hannah Abbott
SLY2302~Euan Abercrombie
SLY2303~Stewart Ackerley
SLY2304~Bertram Aubrey
SLY2305~Avery
SLY2306~Malcolm Baddock
SLY2307~Marcus Belby
SLY2308~Katie Bell
SLY2309~Sirius Orion Black
Grades
TRAN~1~2011-2012~SLY2301~AB
TRAN~1~2011-2012~SLY2302~B
TRAN~1~2011-2012~SLY2303~B
TRAN~1~2011-2012~SLY2305~A
TRAN~1~2011-2012~SLY2306~BC
TRAN~1~2011-2012~SLY2308~A
TRAN~1~2011-2012~SLY2309~AB
CHAR~1~2011-2012~SLY2301~A
CHAR~1~2011-2012~SLY2302~BC
CHAR~1~2011-2012~SLY2303~B
CHAR~1~2011-2012~SLY2305~BC
CHAR~1~2011-2012~SLY2306~C
CHAR~1~2011-2012~SLY2307~B
CHAR~1~2011-2012~SLY2308~AB
EndOfInput
Expected Output
SLY2301~Hannah Abbott~9.5
SLY2302~Euan Abercrombie~7.5
SLY2303~Stewart Ackerley~8.0
SLY2304~Bertram Aubrey~0
SLY2305~Avery~8.5
SLY2306~Malcolm Baddock~6.5
SLY2307~Marcus Belby~8.0
SLY2308~Katie Bell~9.5
SLY2309~Sirius Orion Black~9.0
I managed to solve it using objects but is there any other way to write the code without using objects?
import sys
from Courses.Courses import Course
from Students.Students import Student
from Grades.Grades import Grade
courses = []
students = []
grades = []
gradeDict = {'A':10,'AB':9,'B':8,'BC':7,'C':6,'CD':5,'D':4}
courseCodeDict = {}
def readInput():
isSectionStart=True
while True:
# Reading data from console
input_var = raw_input()
if "EndOfInput" != input_var:
if input_var in "Courses Students Grades":
section=input_var
isSectionStart=True
else:
isSectionStart=False
if not isSectionStart:
extractDataFromRawData(input_var,section)
else:
break;
#printData(courses,students,grades)
calculateGradeAverage(grades,courses)
def calculateGradeAverage(grades,courses):
print("Calculating Average now...")
gradeRollNumberDict={}
courseGradeDict={}
gradesSet = {}
for course in courses:
courseCodeDict.update({course.course_code : 1})
for grade in grades:
if gradeRollNumberDict.get(grade.roll_number) == None:
grade.totalGradePoint = grade.grade
gradeRollNumberDict.update({grade.roll_number : grade.totalGradePoint})
else:
grade.totalGradePoint= grade.grade + gradeRollNumberDict.get(grade.roll_number)
gradeRollNumberDict.update({grade.roll_number : grade.totalGradePoint})
if courseGradeDict.get(grade.roll_number) == None:
grade.totalCourseTaken = courseCodeDict.get(grade.course_code)
courseGradeDict.update({grade.roll_number : courseCodeDict.get(grade.course_code)})
else:
grade.totalCourseTaken= courseCodeDict.get(grade.course_code) + courseGradeDict.get(grade.roll_number)
courseGradeDict.update({grade.roll_number : grade.totalCourseTaken})
for grade in grades:
grade.avgGrade = grade.totalGradePoint/grade.totalCourseTaken
grade.avgGrade = round(grade.avgGrade)
seenGrades = set()
uniqueGrades = []
grades.reverse()
for grade in grades:
if grade.roll_number not in seenGrades:
uniqueGrades.append(grade)
seenGrades.add(grade.roll_number)
#uniqueGrades.reverse()
for a in uniqueGrades:
print(a.roll_number)
#print(uniqueGrades)
grades=uniqueGrades
grades.sort(key=lambda grade:grade.roll_number)
for grade in grades:
print("RollNumber: {0} \t Total CourseTaken: {1} \t Total Grade Point: {2} \t Avg Grade: {3}".format(grade.roll_number,grade.totalCourseTaken,grade.totalGradePoint,grade.avgGrade))
def extractDataFromRawData(input_data,section):
if "Courses" == section:
courses.append(createCourseObject(input_data))
elif "Students" == section:
students.append(createStudentObject(input_data))
elif "Grades" == section:
grades.append(createGradeObject(input_data))
else:
print("Invalid input!!! Exiting the system...")
sys.exit()
def createCourseObject(input_data):
courseInputData = input_data.split("~")
course = Course(courseInputData[0],courseInputData[1],courseInputData[2],courseInputData[3],courseInputData[4])
return course
def createStudentObject(input_data):
studentInputData = input_data.split("~")
student = Student(studentInputData[0],studentInputData[1])
return student
def createGradeObject(input_data):
gradeInputData = input_data.split("~")
grade = Grade(gradeInputData[0],gradeInputData[1],gradeInputData[2],gradeInputData[3],gradeDict[gradeInputData[4]])
return grade
def printData(courses,students,grades):
printObject(courses,"Courses")
printObject(students,"Students")
printObject(grades,"Grades")
def printObject(list,object):
print("Printing %s"%object)
for data in list:
print(data)
if __name__ == '__main__':
readInput()
Code:
from collections import OrderedDict
from pprint import pprint as pp
SEPARATOR = "~"
GRADE_DICT = {
"A": 10,
"AB": 9,
"B": 8,
"BC": 7,
"C": 6,
"CD": 5,
"D": 4
}
def read_input_from_file(file_name="input.txt"):
course_list= list()
student_list = list()
grade_list = list()
section_map = {
"Courses": course_list,
"Students": student_list,
"Grades": grade_list,
}
with open(file_name) as f:
current_item = None
for line in f:
line = line.strip()
if line in section_map:
current_item = section_map[line]
elif line == "EndOfInput":
break
elif current_item is not None:
current_item.append(line)
else:
print("Ignoring line: {}".format(line))
return course_list, student_list, grade_list
def convert_names(name_list):
ret = OrderedDict()
for element in name_list:
id, name = element.split(SEPARATOR)
ret[id] = name
return ret
def convert_grades(grade_list):
ret = dict()
for element in grade_list:
course_id, student_id, grade_id = element.rsplit(SEPARATOR, 2)
ret.setdefault(student_id, dict())[course_id] = grade_id
return ret
def main():
course_list, student_list, grade_list = read_input_from_file()
student_dict = convert_names(student_list)
print("\n[SECTION 0]: Student IDs and names:\n")
pp(student_dict)
exam_stat_dict = convert_grades(grade_list)
print("\n[SECTION 1]: Grades organized by students and courses:\n")
pp(exam_stat_dict)
print("\n[SECTION 2]: Final Grades:\n")
for student_id in student_dict:
if student_id in exam_stat_dict:
grade_dict = exam_stat_dict[student_id]
grades_sum = sum([GRADE_DICT.get(item, 0) for item in grade_dict.values()])
print(SEPARATOR.join([student_id, student_dict[student_id], str(grades_sum/len(grade_dict))]))
else:
print(SEPARATOR.join([student_id, student_dict.get(student_id), "0.0"]))
if __name__ == "__main__":
main()
Output (I'm placing it before the Notes, since I'm going to refer to it from there):
(py35x64_test) c:\Work\Dev\StackOverflow\q45987148>python a.py
[SECTION 0]: Student IDs and names:
OrderedDict([('SLY2301', 'Hannah Abbott'),
('SLY2302', 'Euan Abercrombie'),
('SLY2303', 'Stewart Ackerley'),
('SLY2304', 'Bertram Aubrey'),
('SLY2305', 'Avery'),
('SLY2306', 'Malcolm Baddock'),
('SLY2307', 'Marcus Belby'),
('SLY2308', 'Katie Bell'),
('SLY2309', 'Sirius Orion Black')])
[SECTION 1]: Grades organized by students and courses:
{'SLY2301': {'CHAR~1~2011-2012': 'A', 'TRAN~1~2011-2012': 'AB'},
'SLY2302': {'CHAR~1~2011-2012': 'BC', 'TRAN~1~2011-2012': 'B'},
'SLY2303': {'CHAR~1~2011-2012': 'B', 'TRAN~1~2011-2012': 'B'},
'SLY2305': {'CHAR~1~2011-2012': 'BC', 'TRAN~1~2011-2012': 'A'},
'SLY2306': {'CHAR~1~2011-2012': 'C', 'TRAN~1~2011-2012': 'BC'},
'SLY2307': {'CHAR~1~2011-2012': 'B'},
'SLY2308': {'CHAR~1~2011-2012': 'AB', 'TRAN~1~2011-2012': 'A'},
'SLY2309': {'TRAN~1~2011-2012': 'AB'}}
[SECTION 2]: Final Grades:
SLY2301~Hannah Abbott~9.5
SLY2302~Euan Abercrombie~7.5
SLY2303~Stewart Ackerley~8.0
SLY2304~Bertram Aubrey~0.0
SLY2305~Avery~8.5
SLY2306~Malcolm Baddock~6.5
SLY2307~Marcus Belby~8.0
SLY2308~Katie Bell~9.5
SLY2309~Sirius Orion Black~9.0
Notes:
This is a "slightly" modified version of your code, that only uses stuff from Python standard library
Code explanation:
read_input_from_file (since it's only a helper function, I'm not going to insist much on it):
I saved the input (copy/paste) in a file (called it input.txt), and every time the program runs, it loads the data from there (the reason is obvious)
It (populates and) returns 3 lists (curses, students and grades from your code)
convert_names:
Converts every student name entry (as given in input) into a dictionary*: {id: name} (e.g. "SLY2301~Hannah Abbott" -> {"SLY2301": "Hannah Abbott"}) - the key will be id
*Since in a regular Python dictionary ([Python]: Mapping Types — dict) the keys are ordered by their hash (the hash function can change between Python versions), there's almost 100% chance that the dictionary elements won't be stored in the order they were inserted (as an example you could type in the Python console {1:2, 0:1} and you'll see that it will output {0: 1, 1: 2}), I'm using [Python]: class collections.OrderedDict([items]) which ensures the key order
The return value can be seen in program output (SECTION 0)
convert_grades:
This is where (most of) the magic takes place
Converts every grade entry (as given in input) in a dictionary: {student_id : {course_id: grade_id}} (the last 2 values are aggregated in an inner dictionary; e.g. "TRAN~1~2011-2012~SLY2301~AB" -> {"SLY2301": {"TRAN~1~2011-2012": "AB"}}). For that, I'm using [Python]: str.rsplit(sep=None, maxsplit=-1) with a maxsplit value of 2, as I don't care about the ~s in TRAN~1~2011-2012
If a student_id is present more than once (was to more than 1 course exam), I am just adding the course_id and grade_id in the inner dictionary (this is where [Python]: setdefault(key[, default]) comes into play)
The return value can be seen in program output (SECTION 1)
main:
The program main function. Here, I'm making use of the other functions and display the final data in a proper manner to the user (SECTION 2)
If there was a student that wasn't at any exam, like Bertram Aubrey (the id is not present in the exam statistics dictionary), I just print the id, name and 0.0
Otherwise, I calculate the arithmetic average from the grades in the inner dictionary (I am using [Python]: list Comprehensions to convert the grades into actual numbers, [Python]: sum(iterable[, start]) to sum the grades, then I divide the total by the number of inner dictionary keys) and display it, together with the id and name
The code runs with Python3 and Python2
#EDIT0:
Adding read_input function (read_input_from_file with minimum and trivial modifications) to read input from keyboard:
def read_input():
course_list= list()
student_list = list()
grade_list = list()
section_map = {
"Courses": course_list,
"Students": student_list,
"Grades": grade_list,
}
current_item = None
while(1):
line = input()
if line in section_map:
current_item = section_map[line]
elif line == "EndOfInput":
break
elif current_item is not None:
current_item.append(line)
else:
print("Ignoring line: {}".format(line))
return course_list, student_list, grade_list
Notes:
In order for this function to work with Python2, this code should be added at the beginning of the file:
import sys
if sys.version_info.major < 3:
input = raw_input
You can also use the input.txt file to test the code with large datasets (like provided in the question, without having to manually type all the data) like this:
python a.py < input.txt
#CristiFati using your code i managed to tweak to solve my problem as below.
from collections import OrderedDict
import sys
SEPARATOR = "~"
GRADE_DICT = {
"A": 10,
"AB": 9,
"B": 8,
"BC": 7,
"C": 6,
"CD": 5,
"D": 4
}
def read_input_from_file():
course_list= list()
student_list = list()
grade_list = list()
section_map = {
"Courses": course_list,
"Students": student_list,
"Grades": grade_list,
}
current_item = None
while True:
line = input()
#line = line.strip()
if line != "EndOfInput":
if line in section_map:
current_item = section_map[line]
elif current_item is not None:
current_item.append(line)
else:
print("Ignoring line: {}".format(line))
else:
break
return course_list, student_list, grade_list
def convert_names(name_list):
ret = OrderedDict()
for element in name_list:
id, name = element.split(SEPARATOR)
ret[id] = name
return ret
def convert_grades(grade_list):
ret = dict()
for element in grade_list:
course_id, student_id, grade_id = element.rsplit(SEPARATOR, 2)
ret.setdefault(student_id, dict())[course_id] = grade_id
return ret
def main():
course_list, student_list, grade_list = read_input_from_file()
student_list.sort()
student_dict = convert_names(student_list)
exam_stat_dict = convert_grades(grade_list)
for student_id in student_dict:
if student_id in exam_stat_dict:
grade_dict = exam_stat_dict[student_id]
grades_sum = sum([GRADE_DICT.get(item, 0) for item in grade_dict.values()])
print(SEPARATOR.join([student_id, student_dict[student_id], str(round(float(grades_sum/len(grade_dict)),2))]))
else:
print(SEPARATOR.join([student_id, student_dict.get(student_id), "0"]))
if __name__ == "__main__":
main()

UnboundLocalError: local variable 'key' referenced before assignment

I am trying to import a text file and encrypt/decrypt by two key words. I set a key variable but can't find the correct place to locate it.
Here is where it currently is:
def importFile():
importText = []
file = input('What is the text file name: ')
fileName = open(file,'r')
text = fileName.read()
fileName.close()
fileName = text
message = text
#print (text)
delete = open(file,'w')
delete.write('')
key = input ('What key do you wnat to use: ')
Here is where the key is called:
def translatedMessage(mode):
translated = []
keyIndex = 0
key = key.upper()
for symbol in message:
num =LETTERS .find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS .find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS .find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
If you need it here is it all together:
LETTERS = 'ZABCDEFGHIJKLMNOPQRSTUVWXY'
def main():
myMode = input("Encrypt 'e' or Decrypt 'd': ")
if myMode == 'encrypt' or myMode == 'e':
translated = encryptFile()
elif myMode == 'decrypt' or myMode == 'd':
translated = decryptFile()
def importFile():
importText = []
file = input('What is the text file name: ')
fileName = open(file,'r')
text = fileName.read()
fileName.close()
fileName = text
message = text
#print (text)
delete = open(file,'w')
delete.write('')
key = input ('What key do you wnat to use: ')
def encryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
importFile()
return translatedMessage('encrypt')
def decryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
importFile()
return translatedMessage('decrypt')
def translatedMessage(mode):
translated = []
keyIndex = 0
key = key.upper()
for symbol in message:
num =LETTERS .find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS .find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS .find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
I'm pretty new to coding and know this is pretty simple so any advice is greatly appreciated:)
The problem in your code is that you are treating key like a global variable, but it is a local one, so you need to pass it between your functions:
LETTERS = 'ZABCDEFGHIJKLMNOPQRSTUVWXY'
def main():
myMode = input("Encrypt 'e' or Decrypt 'd': ")
if myMode == 'encrypt' or myMode == 'e':
translated = encryptFile()
elif myMode == 'decrypt' or myMode == 'd':
translated = decryptFile()
def importFile():
importText = []
file = input('What is the text file name: ')
fileName = open(file,'r')
text = fileName.read()
fileName.close()
fileName = text
message = text
#print (text)
delete = open(file,'w')
delete.write('')
return input ('What key do you wnat to use: ') # Return the key
def encryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
key = importFile() # Get the key returned by the function
return translatedMessage('encrypt', key) # Pass the key to the function
def decryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
key = importFile() # Get the key returned by the function
return translatedMessage('decrypt', key) # Pass the key to the function
def translatedMessage(mode, key): # `key` is an argument
translated = []
keyIndex = 0
key = key.upper()
for symbol in message:
num =LETTERS .find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS .find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS .find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
A simpler solution would be to define key as a global variable by adding the line global key to the importFile() function. In general however, I think using the global keyword in Python is discouraged.
This explanation of global vs. local variables in Python might be helpful: http://www.python-course.eu/global_vs_local_variables.php

How to repeat blocks of code in Python

I've created a code that allows a user to view the average score of the values that are in the file. In Example the Text File would look like the following:
Text File For Class 1: it is similar for each text file ; 2 and 3. just different names and values
Matt 2
Sid 4
Jhon 3
Harry 6
There are 3 classes altogether in which the user is prompted to choose which class they want to preview.
Code:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
one = "1.txt"
two = "2.txt"
three = "3.txt"
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
Question
If i wanted to Keep Repeating the code above so that the user can keep using it until they want to exit. so, is it possible to put the code into a while loop and only stop the code if the user wants to, i.e the user is prompted if they want to choose another option and class.
NB: there will be other options such as alphabetical order however right now i only want to know how to do it for the average section.
Best thing you can do is to make a loop for user input and write a function for listing the file.
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = ""
options = ["1", "2", "3"]
one = "1.txt"
two = "2.txt"
three = "3.txt"
def read_text_file(file): # standalone function for viewing files to reduce duplicate code
file += ".txt"
with open(file) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
while True:
option = input("option [avg]: ").lower()
if option == "exit":
break # checks if user want to exit a program
else:
option_class = input("class: ")
if option == 'avg' and option_class in options:
read_text_file(option_class)
else:
print("nothing to show, asking again")
print("end of program")
As I mentioned in the comment section, you should leverage the power of functions here. By breaking down your components to manageable pieces, you actually afford yourself readability and flexibility. See code below, where I have two functions, one for averages and one for totals.
def get_class_average(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
return avg
except:
print "No file with that name found."
def get_class_total(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
return b
except:
print "No file with that name found."
def check_class_number(string_input):
try:
int(string_input)
return True
except ValueError:
return False
if __name__ == "__main__":
while True:
input_val = raw_input(
"Enter class number (enter 'exit' to quit program): ")
if input_val == 'exit':
break
if check_class_number(input_val): # If it's a valid class number.
method = raw_input("Enter method: ")
if method == 'avg':
avg = get_class_average(int(input_val))
print "The average of Class {0} is {1}".format(input_val, avg)
elif method == 'sum':
total = get_class_total(int(input_val))
print "The total of Class {0} is {1}".format(input_val, total)
else:
print "That is not a valid class number."
continue
Sample run:
The really fun part here is that you can even refactor get_class_average and get_class_total to be a single function that checks if the passed in method is avg or sum and returns the respective values from there (this is easily doable since you have practically the same lines of code for both functions, get_class_average just has an extra division involved).
Have fun.
Yes, you can just put your code within a while-loop and prompt the user for input:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
# End main_menu()
one = "1.txt"
two = "2.txt"
three = "3.txt"
keepGoing = True
while(keepGoing):
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
# Prompt user for input on whether they want to continue or not:
while(True):
keepGoingStr = input("Would you like to continue? (Y/N)\n>>> ").lower()
if(keepGoingStr[0] == 'y'):
# Keep going
keepGoing = True
break
elif(keepGoingStr[0] == 'n')
# Stop
keepGoing = False
break
else:
print("Sorry, your input did not make sense.\nPlease enter either Y or N for yes or no.")
# end if
# end while - keep going input
# End While(keepGoing)
As mentioned in the comments, though, you should consider breaking up your code into functions.

Saving objects to a list python; List not updating for some reason?

Alright so what I am trying to do is to get objects to save in list form when a user creates a NoteSet. It appends the objects to the list db properly when I input NoteSet('ex','example',True). I made a function called makeNewNoteSet() and it seems to be working correctly but it doesnt append to the db list. I can not figure out why.
import sys
import datetime
import pickle
notesets = []
db = []
def save():
global db
filename = "notesets.dat"
file = open(filename, "wb")
if file == None:
print("There was an error creating your file")
return
pickle.dump(db, file)
file.close()
print("Saved words to ",filename)
def load():
global db
filename = "notesets.dat"
file = open(filename, "rb")
db = pickle.load(file)
print("There are ",len(db)," Note Sets")
file.close()
class NoteSet:
nextseqNum = len(db)+2
def __init__(self,name,description,hidden):
global db
self.seqNum = NoteSet.nextseqNum
self.name = name
self.description = description
self.dateCreated = datetime.date.today()
self.hidden = hidden
self.notes = list()
NoteSet.nextseqNum += 1
print(self)
notesets.append(self)
notelist = [self.seqNum,self.name,self.description,self.dateCreated,self.hidden,self.notes]
print(notelist)
db.append(notelist)
NoteSet.nextseqNum += 1
def __str__(self):
printstr = str(self.seqNum),self.name,self.description,str(self.dateCreated)
printstr = str(printstr)
return printstr
class Note:
nextseqNum = 0
def __init__(self,text,dateCreated,description,category,priority,hidden):
self.text = text
self.dateCreated = str
self.dateRead = str
self.description = str
self.category = str
self.priority = int
self.hidden = bool
self.seqNum = Note.nextseqNum
Note.nextseqNum += 1
def main():
while True:
load()
printMainMenu()
selection = int(input("? "))
if selection == 1:
listNoteSets()
elif selection == 2:
listAllNoteSets()
elif selection == 3:
makeNewNoteSet()
elif selection == 4:
selectNoteSet() # this makes the working note set
elif selection == 5:
deleteNoteSet()
elif selection == 6:
sys.exit()
else:
print("Invalid choice")
def printMainMenu():
print("1. List note sets")
print("2. List all note sets (including hidden sets)")
print("3. Make a new note set")
print("4. Select a working note set")
print("5. Delete a note set")
print("6. Quit")
def listNoteSets():
num = 0
for row in db:
if db[num][4] == False:
print('#',db[num][0],' ',db[num][1],'----',db[num][2])
num += 1
input("[Press return to see main menu]")
main()
def listAllNoteSets():
num = 0
for row in db:
print('#',db[num][0],' ',db[num][1],'----',db[num][2])
num += 1
input("[Press return to see main menu]")
main()
def makeNewNoteSet():
num = 0
name = input("What would you like to name your note set? --- ")
for row in db:
if name == db[num][1]:
print("That note set has already been created")
makeNewNoteSet()
description = input("Describe your note set briefly --- ")
hidden = input("Would you like this note set to be hidden? --- ")
if hidden == 'y' or 'yes':
hidden = True
else:
hidden = False
NoteSet(name, description, hidden)
print("noteset created you can now access it through the menu")
input("[Press enter to return to menu]")
main()
def selectNoteSet():
num = 0
for row in db:
print('#',db[num][0],' ',db[num][1],'----',db[num][2])
num += 1
response = input("Enter the number assosciated with the noteset you would like to access")
print("Note set #",response," was selected")
main()
After you add a new note in makeNewNoteSet(), you call main() which calls load() which overwrites the in-memory copy of the database you just changed. You probably want to call save() somewhere in there.

Categories

Resources