Hello everyone,

I'm a beginner in programming languages and in Python. I came across this error and I don't khow if it is a logical error or a design error. The problem is with class_average

a = {1:[1, 2, 3],
     2:[3,4,5],
     3:[6,7,8]
     }

b = {1:[3,7,4],
     2:[8,2,9],
     3:[3,6,3]
     }

c = {1:[4,7,1],
     2:[5,5,9],
     3:[2,3,7]
     }

p=[a,b,c]

def average(p):
    return sum(p)/len(p)

def get_average(d):
    return average(p[1]) + average(p[2]) + average(p[3])

def class_average(p):
    for item in p:
        retun average(get_average(item))

or

def class_average(p):
    for item in p:
        return sum(get_average(item))

You came across what error? If you're getting an error message, please post it. If your code acts differently than you want it to, please explain what you expect and in what way it acts differently.

PS: Using return inside a for loop like you're doing, will likely not do what you want (though that does of course depend on what you want). return leaves the function immediately, so when you do it in a loop (without an if around it), that means you will exit the loop after the first element and never even look at the other elements.

PPS: On line 26 you misspelled return. You can tell because it's not highlighted as a keyword.

There is a typo in get_average that you should be able to run down from the error messages, or at least begin to learn how. Using descriptive variable names would help you with this, as well as help us understand the program. Print the return from get_average and see if it can be summed. Note that get_average returns a kind of sum of averages, not the average. Also, you should loop through containers like a dictionary so your funtion can handle containers that have any number of items instead of

return average(p[1]) + average(p[2]) + average(p[3])

Usually we test programs with known values that should produce known results to tell if the program is calculating correctly or not, so what are the results supposed to be?.

Edited 3 Years Ago by woooee

Also be aware that in Python2 you might get an integer division unless you force a float:

def average(q):
    ''' cast a float for Python2 '''
    return float(sum(q))/len(q)

q = [1, 2, 3, 4]

avg = average(q)

print(avg)  # 2.5

Yes, get_average should be:

def get_average(d):
    return average(d[1]) + average(d[2]) + average(d[3])

and the class_average is better:

def class_average(p):
    for item in p:
        temp = average(get_average(item))
    return temp

or

  def class_average(p):
        for item in p:
            temp = sum(get_average(item))
        return temp

the error I get is when I call class_average(p)

 Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    class_average(p)
  File "/Users/gam/Desktop/class.py", line 28, in class_average
    temp = sum(get_average(item))
TypeError: 'float' object is not iterable

It was an exercise in a tutorial to get the class averege for group of students and I thought of this.

Edited 3 Years Ago by gmorcan

class average should update by accumulating the initialized sum by += not overwrite variable by =. You should take probably also average, not sum.

Here little more advanced version for averaging total items.

values = [item for value in my_dict.items() for item in value]
average = float(sum(values)) / len(values)

Edited 3 Years Ago by pyTony

You get that error because you call with get_average with item as its argument, but item is a float and get_average expects to get a list, not a single float.

@ sepp2k That's not true. item is every element from the list of dictionaries p so item is a dictionary. get_average returns the average for key values 1,2,3 from a dictionary, however it should return (average(d[1]) + average(d[2]) + average(d[3]))/3

@pyTony is right. The problem is that I overwrite the variable by = instead of accumulating it by +=.

That's not true. item is every element from the list of dictionaries p so item is a dictionary.

Right, my mistake, the error was that you called sum on the result of get_average. get_average returns a float, but sum expects an iterable.

You should be able to come up with a generic function that takes any number of dictionaries of any length and calculates the average.

a = {1:[1, 2, 3],
     2:[3,4,5],
     3:[6,7,8]
     }

b = {1:[3,7,4],
     2:[8,2,9]
     }

c = {1:[4,7,1],
     2:[5,5,9],
     3:[2,3,7],
     4:[9, 10, 11]
     }


def average(tuple_of_dicts):  ## or list of dicts
    """ receives a tuple of one or more dictionaries and
        averages the grades
    """
    total_grades=0
    total_num=0
    for each_dictionary in tuple_of_dicts:
        for key in each_dictionary:
            grades_list = each_dictionary[key]
            for grade in grades_list:
                total_grades += grade
                total_num += 1
    return float(total_grades)/total_num

print "One dictionary =", average([a])  ## can use a tuple or list
print "Two dictionaries =", average((a, b))
print "Three dictionaries =", average([a, b, c])

Edited 3 Years Ago by woooee

This question has already been answered. Start a new discussion instead.