Maddie
Maddie

Reputation: 41

I can't properly define a function in Python. Can anyone tell me where I am going wrong?

The directions are to: Write a function called calc_average that takes a string representing a filename of the following format, for example:

Smith 82
Jones 75
Washington 91

The function should calculate and return the class average from the data in the file.

So far I have:

def calc_average():
    infile = open("filename.txt", "r")
    readlines = infile.readlines()
    for line in readlines:
        parts = line.split()
        name = parts[0]
        clsavg = parts[1]
        average = 0

I have tried to work past this part, but I can't find the right way to do the average. Any suggestions? I only need the function and the file is only an example.

Upvotes: 0

Views: 239

Answers (7)

fpeelo
fpeelo

Reputation: 382

First thing you're doing wrong is not marking the source code in your post, as source code. Put it on separate lines to the rest of your post, and use the {} link at the top of the editor to mark it as source code. Then it should come out like this:

def calc_average(): 
  infile = open("filename.txt", "r") 
  readlines = infile.readlines() 
  for line in readlines: 
    parts = line.split() 
    name = parts[0] 
    clsavg = parts[1] 
    average = 0

You should do the same with the file contents: I am assuming that you have one name and one number per line.

If you want to put a snippet of code inline with your text, e.g. "the foo() function", put a backtick each side of the code. The backtick is like an accent grave, and is sometimes very wrongly used as an opening quote char in text files.

Next, you were to write a function that takes a string containing a filename. But you have

def calc_average(): 
  infile = open("filename.txt", "r") 

That doesn't take anything. How about

def calc_average(filename): 
  infile = open(filename, "r") 

Now, what your function is doing is, reading the lines ok, splitting them into a name and a number -- but both are still strings, and the string containing the number is put in the variable clsavg, and then just setting the variable average to 0 every time a line is read.

But what do you want to do? I think when you say "class average", these are all people in a class, the numbers are their scores, and you want to calculate the average of the numbers? So that means adding up all the numbers, and dividing by the number of rows in the file.

So you need to set a variable to 0 ONCE, before the loop starts, then on each time you read a line, increment it by the number value. I would imagine the clsavg variable would be the one to use. So you need to convert parts[1] to an integer. You can use int() for that. Then you need to increment it, with += or with a statement like x = x + y. Ask google if you want more details. That way you build up a total value of all the numbers. Finally, after the loop is finished (meaning on a line that is only indented as far as the for), you need to divide the total by the number of rows. That would be the number of elements in readlines. You should google the len() function. Division uses the / operator. You can use x /= y to set x to the value of x/y.

That's making lots of assumptions: that you want an integer average, that every line in the file has the name and number (no blank lines or comments etc.) By the way, you can use float() instead of int() if you want more precision.

Upvotes: 0

itzMEonTV
itzMEonTV

Reputation: 20339

You didnt calculated the average.Also didnt return anything from the function calc_average.So try this

def calc_average():
    with open('filename.txt') as text:
        nums = [int(i.split()[1]) for i in text]
        avg = float(sum(nums)) / float(len(nums))
        return avg
>>>print(calc_average())
82.6666666667

Upvotes: 0

inspectorG4dget
inspectorG4dget

Reputation: 113905

Alright, let's look at this, part by part:

Write a function called calc_average

def calc_average():

that takes a string representing a filename

let's make this a meaningful variable name:

def calc_average(filename):

Now that we have the basics down, let's talk about how to actually solve your problem:

Each line in your file contains a name and a grade. You want to keep track of the grades so that you can compute the average out of them. So, you need to be able to:

  1. read a file one line at a time
  2. split a line and take the relevant part
  3. compute the average of the relevant parts

So, it seems that holding the relevant parts in a list would be helpful. We would then need a function that computes the average of a list of numbers. So let's write that

def average(L):
    sum = 0
    for num in L:
        sum += num
    return sum/len(L)

Of course, there's an easier way to write this:

def average(L):
    return sum(L)/len(L)  # python has a built-in sum function to compute the sum of a list

Now that we have a function to compute the average, let's read the file and create a list of numbers whose average we want to compute:

def read_from_file(filename):
    answer = []  # a list of all the numbers in the file
    with open(filename) as infile:  # open the file to read
        for line in infile:
            parts = line.split()
            grade = int(parts[-1])  # the integer value of the last entity in that line
            answer.append(grade)
    return answer

Now that we have a function that returns the relevant information from a file, and a function that computes averages, we just have to use the two together:

def calc_average(filename):
    numbers = read_from_file(filename)
    answer = average(numbers)
    return answer

Now, you might notice that you don't need to keep track of each number, as you just sum them up and divide by the number of numbers. So, this can be done more concisely as follows:

def calc_average(filename):
    nums = 0
    total = 0
    with open(filename) as infile:
        for line in infile:
            total += int(line.split()[-1])
            nums += 1
    return total/nums

Upvotes: 0

Scott
Scott

Reputation: 6389

To continue using mostly your own code and your example, you could do:

def calc_average(filename):
    infile = open(filename, "r")
    readlines = infile.readlines()
    average = 0 # use this to sum all grades
    index = 0 # keep track of how many records or lines in our txt
    for line in readlines:
        parts = line.split()
        name = parts[0] # basically useless
        # for each line in txt we sum all grades
        average = average + float(parts[1]) # need to convert this string to a float
        index = index + 1
    # divide by the number of entries in your txt file to get the class average
    return average / index

then:

calc_average('grades.txt')

prints:

82.66666666666667

Upvotes: 0

user4638313
user4638313

Reputation:

def calc_average():
    infile = open("filename.txt", "r")
    readlines = infile.readlines()
    for line in readlines:
        parts = line.split()
        name = parts[0]
        clsavg = parts[1]
        average = 0

After all that, you're just literally sending something into the function, but not asking for anything to come out.

Using return will help get something out of the function.

return [variable] is a way to use it.

Here:

Add this line return [variable] to the end of your code, such that it looks like this:

def calc_average():
    infile = open("filename.txt", "r")
    readlines = infile.readlines()
    for line in readlines:
        parts = line.split()
        name = parts[0]
        clsavg = parts[1]
        average = 0
    return variable #where you replace variable with 
                    #the thing you want to get out of your function

To call this function (or should i say "run" it) just write the name of it, but dedented.

def calc_average():
    infile = open("filename.txt", "r")
    readlines = infile.readlines()
    for line in readlines:
        parts = line.split()
        name = parts[0]
        clsavg = parts[1]
        average = 0
    return variable
calc_average() #<- this calls the function

You might also want to read up on parameters:

parametere are values passed into a function and are used.

Example:

def test1(number):
    number = number + 1 #this can be written as number += 1 as well
    return number
x = test1(5)

First I define the function with a number parameter. This would mean that number will be used in this function. Notice how the lines below def test1(number) also use the variable number. whatever is passed into the function as number will be considered number in the function.

Then, I call the function and use 5 as a parameter.

When it's called, the function takes 5 (since that was the input parameter) and stores the variable number as 5.(from def test1(number)) Thus, It's like writing number = 5 in the function itself.

Afterwards, return number will take the number (which in this case is added to become 6, number = 6) and give it back to the outside code. Thus, it's like saying return 6.

Now back to the bottom few lines. x = test1(5) will make x = 6, since the function returned 6.

Hope I helped you understand functions more.

Upvotes: 2

user3056150
user3056150

Reputation: 15

def calc_average():
    infile = open("filename.txt", "r")
    readlines = infile.readlines()
    clsavg = 0
    counter = 0
    for line in readlines:
        parts = line.split()
        clsavg =  clsavg+ float(parts[1])
        counter = counter + 1
    print clsavg/counter

Upvotes: 0

John Kugelman
John Kugelman

Reputation: 361575

The function needs an argument. It also needs to return the average, so there should be a return statement at the end.

def calc_average(file_name):
    ...
    return <something>

Upvotes: 0

Related Questions