For my beginners course python I got the following assignment:
In the input file, grades are listed for the geography tests of group 2b. There have been three tests of which the grades will be included in the half-yearly report that is given to the students before the Christmas break. On each line of the input you can find the name of the student, followed by one or more under scores (’_’). These are succeeded by the grades for the tests, for example:
Anne Adema____________6.5 5.5 4.5
Bea de Bruin__________6.7 7.2 7.7
Chris Cohen___________6.8 7.8 7.3
Dirk Dirksen__________1.0 5.0 7.7
The lowest grade possible is a 1, the highest a 10. If somebody missed a test, the grade in the list is a 1. Your assignment is to make the report for the geography course of group 2b, which should look like this:
Report for group 2b
Anne Adema has an average grade of 5.5
Bea de Bruin has an average grade of 7.2
Chris Cohen has an average grade of 7.3
Dirk Dirksen has an average grade of 4.6
End of report
This is my python code so far:
NUMBER_OF_GRADES = 3
file =open('grades1.in.txt').read().split('\n')
for scores in file:
name_numbers = (scores.split('_'))
def averages ():
for numbers in file:
sum=0
numbers = split("\n")
for num in numbers:
sum = sum + int(num)
averages = sum/NUMBER_OF_GRADES
print ('% has an average grade of %.1') %(name, averages)
Where does it go wrong? What am I missing? Am I not splitting the right way?
There's a few things wrong with your code. This maybe should be migrated to Code Review, but I'll write my answer here for now.
I will keep this as close to your version as I can so that you see how to get from where you are to a working example without needing a ton of stuff you might not have learned yet. First let's look at yours one part at a time.
file =open('grades1.in.txt').read().split('\n')
Your file
is going to be a list of strings, where each string is a line in your input file. Note that if you have empty lines in your input, some of the lines in this list will be empty strings. This is important later.
for scores in file:
name_numbers = (scores.split('_'))
Works fine to split the name part of the line from the scores part of the line, so we'll keep it, but what are you doing with it here? Right now you are overwriting name_numbers
with each new line in the file and never doing anything with it, so we are going to move this into your function and make better use of it.
def averages():
No arguments? We'll work on that.
for numbers in file:
Keep in mind your file
is a list, where each entry in the list is one line of your input file, so this numbers in file
doesn't really make sense. I think this is where you first go wrong. You want to look at the numbers in each line after you split it with scores.split('_')
, and for that we need to index the result of the split. When you split your first line, you get something like:
split_line = ['Anne Adema', '', '', '', '', '', '', '', '', '', '', '', '6.5 5.5 4.5']
The first element (split_line[0]
) is the name, and the last element (split_line[-1]
) are the numbers, but you still have to split those out too! To get a list of numbers, you actually have to split it and then interpret each string as a number. You can do this pretty easily with a list comprehension (best way to loop in Python) like this:
numbers = [float(n) for n in split_line[-1].split(' ')]
This reads something like: first split the last element of the line at spaces to get ['6.5', '5.5', '4.5']
(note they're all strings), and then convert each value in that list into a floating-point number, and finally save this list of floats as numbers
. OK, moving on:
sum=0
numbers = split("\n") # already talked about this
for num in numbers:
sum = sum + int(num)
averages = sum/NUMBER_OF_GRADES
sum
is a keyword in Python, and we never want to assign something to a keyword, so something's wrong here. You can actually just call sum(my_list)
on any list (actually any iterable) my_list
to get the sum of all of the values in the list. To take the average, you just want to divide this sum by the length of the list, which you can get with len(my_list)
.
print ('% has an average grade of %.1') %(name, averages)
There are some cool newer ways to print formatted text, one of which I will show in the following, but if you are supposed to use this way then I say stick with it. That said, I couldn't get this line to work for me, so I went with something I know better.
def averages(line):
if line is '':
return # skips blank lines!
name_numbers = line.split('_') # now we split our line
name = name_numbers[0]
numbers = [float(n) for n in name_numbers[-1].split(' ')]
average = sum(numbers) / len(numbers)
print('{} has an average grade of {:.2}'.format(name, average))
And running it on your data:
file =open('grades1.in.txt').read().split('\n')
for line in file:
averages(line) # call the function on each line
# Anne Adema has an average grade of 5.5
# Bea de Bruin has an average grade of 7.2
# Chris Cohen has an average grade of 7.3
# Dirk Dirksen has an average grade of 4.6
With the result shown in the comments below the function call. One more note, you never close your file, and in fact you never save off the file handle to close it. You can get rid of any headaches around this by using the context manager syntax in Python:
with open('grades1.in.txt', 'r') as a_file:
for line in a_file:
averages(line)
This automatically handles closing the file, and will even make sure to do so if you run into an error in the middle of the block of code that executes within the context manager. You can loop through a_file
because it basically acts as an iterable that returns the next line in the file each time it is accessed.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments