在Python中函数中计算平均值

1 投票
3 回答
7020 浏览
提问于 2025-04-18 12:10

我正在学习Python,但遇到了一些困难。在之前的部分一切都很顺利,直到最后一个函数:

def get_class_average(students): 

在这之前的部分都运行得很好,但在最后一个函数那里,我不知道该怎么做才能让它正常工作。我想为每个学生计算平均分,然后再计算这些平均分的平均值,也就是“班级平均分”。所以,我只想知道最后一个函数的答案,而不想改动之前的任何函数:

lloyd = {
    "name": "Lloyd",
    "homework": [90.0, 97.0, 75.0, 92.0],
    "quizzes": [88.0, 40.0, 94.0],
    "tests": [75.0, 90.0]
}
alice = {
    "name": "Alice",
    "homework": [100.0, 92.0, 98.0, 100.0],
    "quizzes": [82.0, 83.0, 91.0],
    "tests": [89.0, 97.0]
}
tyler = {
    "name": "Tyler",
    "homework": [0.0, 87.0, 75.0, 22.0],
    "quizzes": [0.0, 75.0, 78.0],
    "tests": [100.0, 100.0]
}



def average(numbers):
       total = sum(numbers)
       return float(total) / len(numbers)


def get_average(student):
       homework = average(student["homework"]) 
       quizzes = average(student["quizzes"]) 
       tests = average(student["tests"]) 
       return 0.1 * average(student["homework"]) + 0.3 * average(student["quizzes"])    +     0.6 * average(student["tests"])

def get_letter_grade(score):
       if score >= 90:
              return "A"
       elif score >= 80:
              return "B"         
       elif score >= 70:
              return "C"
       elif score >= 60:
              return "D"
       else:
              return "F"

def get_class_average(students):
       results = []
       for student in results:
              get_average(student)
              results.append(student)
              average(student)
              return results

students = [lloyd,alice,tyler]

print get_class_average(students)

我终于找到了这个问题的解决办法。所以,我想把最后一个函数的修正代码贴在下面,get_class_average(students)。现在它可以正常工作了:

def get_class_average(students):
       results = []
       for each in students:
              studentavg = float(get_average(each))
              results.append(studentavg)
       return average(results)

students = [lloyd,alice,tyler]

print get_class_average(students)

3 个回答

0

这个对我有效:

lloyd = {
  "name": "Lloyd",
  "homework": [90.0, 97.0, 75.0, 92.0],
  "quizzes":  [88.0, 40.0, 94.0],
  "tests":    [75.0, 90.0]
}
alice = {
  "name": "Alice",
  "homework": [100.0, 92.0, 98.0, 100.0],
  "quizzes":  [82.0, 83.0, 91.0],
  "tests":    [89.0, 97.0]
}
tyler = {
  "name": "Tyler",
  "homework": [0.0, 87.0, 75.0, 22.0],
  "quizzes":  [0.0, 75.0, 78.0],
  "tests":    [100.0, 100.0]
}

# Add your function below!
def average(numbers):
  total = 0.0
  total = sum(numbers)
  total = float(total) / len(numbers)
  return total

def get_average(student):
  hweight = 0.1
  qweight = 0.3
  tweight = 0.6
  homework = average(student["homework"])
  quizzes  = average(student["quizzes"])
  tests    = average(student["tests"])
  total = (homework * hweight) + (quizzes * qweight) + (tests * tweight)
  return total

def get_letter_grade(score):
  if score >= 90:
    return 'A'
  elif score < 90 and score >= 80:
    return 'B'
  elif score < 80 and score >= 70:
    return 'C'
  elif score < 70 and score >= 60:
    return 'D'
  else:
    return 'F'

def get_class_average(class_list):
  results = []
  for student in class_list:
    running = get_average(student)
    results.append(running)
  return average(results)

students = [lloyd, alice, tyler]
print "The Average for the class is:\n"
print get_class_average(students)
print
print "Which corresponds to a letter grade of:\n"
print get_letter_grade(get_class_average(students))
0

这里有几个学生的信息,每个学生都有名字、作业成绩、测验成绩和考试成绩。

首先,我们定义了三个学生的资料:

lloyd 是一个学生,他的名字是“Lloyd”,他的作业成绩是 [90.0, 97.0, 75.0, 92.0],测验成绩是 [88.0, 40.0, 94.0],考试成绩是 [75.0, 90.0]。

alice 是另一个学生,她的名字是“Alice”,她的作业成绩是 [100.0, 92.0, 98.0, 100.0],测验成绩是 [82.0, 83.0, 91.0],考试成绩是 [89.0, 97.0]。

tyler 是第三个学生,他的名字是“Tyler”,他的作业成绩是 [0.0, 87.0, 75.0, 22.0],测验成绩是 [0.0, 75.0, 78.0],考试成绩是 [100.0, 100.0]。

在下面添加你的函数!

接下来,我们定义了一个计算平均值的函数:

def average(numbers): 这个函数接收一个数字列表,计算这些数字的总和,然后除以数字的个数,最后返回平均值。

然后,我们定义了一个获取学生平均成绩的函数:

def get_average(student): 这个函数会计算学生的作业、测验和考试的平均成绩,并根据不同的权重(作业占10%,测验占30%,考试占60%)来计算总的平均成绩。

接着,我们定义了一个根据分数获取字母等级的函数:

def get_letter_grade(score): 这个函数会根据分数返回相应的字母等级,比如90分以上是“A”,80到89分是“B”,70到79分是“C”,60到69分是“D”,低于60分就是“F”。

然后,我们把所有学生放在一个列表里:

students = [lloyd, alice, tyler]

接下来,我们定义了一个计算班级平均成绩的函数:

def get_class_average(students): 这个函数会遍历每个学生,计算他们的平均成绩,并把结果存到一个列表里,最后返回这个列表的平均值。

最后,我们打印出班级的平均成绩:

print get_class_average(students)

1

你应该知道,平均数的平均数其实是不太正确的。我已经帮你修正了代码,让它能正常工作。下面是修正后的代码:

lloyd = {
    "name": "Lloyd",
    "homework": [90.0, 97.0, 75.0, 92.0],
    "quizzes": [88.0, 40.0, 94.0],
    "tests": [75.0, 90.0]
}
alice = {
    "name": "Alice",
    "homework": [100.0, 92.0, 98.0, 100.0],
    "quizzes": [82.0, 83.0, 91.0],
    "tests": [89.0, 97.0]
}
tyler = {
    "name": "Tyler",
    "homework": [0.0, 87.0, 75.0, 22.0],
    "quizzes": [0.0, 75.0, 78.0],
    "tests": [100.0, 100.0]
}



def average(numbers):
    total = sum(numbers)
    return float(total) / len(numbers)


def get_average(student):
       homework = average(student["homework"]) 
       quizzes = average(student["quizzes"]) 
       tests = average(student["tests"]) 
       return 0.1 * average(student["homework"]) \
            + 0.3 * average(student["quizzes"]) \
        + 0.6 * average(student["tests"])

def get_letter_grade(score):
       if score >= 90:
              return "A"
       elif score >= 80:
              return "B"         
       elif score >= 70:
              return "C"
       elif score >= 60:
              return "D"
       else:
              return "F"

def get_class_average(students):
    results = []
    for student in students:
        a = get_average(student)
        results.append(a)
    return average(results)

students = [lloyd,alice,tyler]

print get_class_average(students)    

因为你刚接触Python,我花了一个多小时重写了你的代码,使用了Python的各种特性,包括文档字符串、生成器、列表推导式、类,还有一些新的导入方式,以及如何对模块进行单元测试。我知道你希望我对你的代码做最小的修改,但我觉得如果只是解决你的问题然后就结束了,这对你来说不太公平。我想给你一些代码片段,使用你的例子,分享我在学习Python时积累的经验。

我的例子比你的要长得多,内容也更复杂,我并不是建议你走比最简单的路线更复杂的路径,我只是提供一个示例。读到这些时不要惊慌,慢慢看,玩一玩,尽量利用它。你可能需要在脑海中和文件系统里反复琢磨一段时间,才能理解这些内容。

如果你想知道 if __name__ == "__main__": 这段代码是干嘛的,我建议你把我的代码保存为一个叫 Student.py 的文件,然后在Python解释器中输入 import Student。注意一下有什么不同的地方 :)。另外,在同一个会话中,调用 import Student(当然要在 Student.py 文件保存的同一目录下),然后输入 help(Student) -- 我保证这会让你觉得很值得。

from __future__ import division # to get rid of having to use float()
from math       import floor, log10 # for a helper function

class Student:
    """
    A class encapsulating elements of a student object. 
    Notable properties:
    homework_weight(0.1) --> a float multiplying student's homework average
    quiz_weight(0.3)     --> a float multiplying the student's quiz average
    test_weight(0.6)     --> a float multiplying the student's test average
    delimiter            --> a character used to separate fields in __str__
    """
    sig_figs        = 2
    homework_weight = 0.1
    quiz_weight     = 0.3
    test_weight     = 0.6
    delimiter       = '|'

    def __init__(self, name, homework, quizzes, tests):
        """
        Constructor for the Student object. Parameters are as follows:
        name      --> a string containing the student's name
        homework  --> a list of floats containing homework grades
        quizzes   --> a list of floats containing quiz grades
        tests     --> a list of floats containing test grades
        """
        self.__name     = name
        self.__homework = homework
        self.__quizzes  = quizzes
        self.__tests    = tests

    def get_name(self):
        """ Returns the current object's name """
        return self.__name

    def get_homeworks(self):
        """ yields a generator object for student's homework grades"""
        for i in self.__homework: yield i

    def get_quizzes(self):
        """ yields a generator object for student's quiz grades"""
        for i in self.__quizzes:  yield i

    def get_tests(self):
        """ yields a generator object for student's test grades"""
        for i in self.__tests:    yield i


    @classmethod
    def from_dict(cls, student_dict):
        """
        Creates a Student object from a dictionary. The dictionary must
        contain the following key-value pairs:
        'name'     : student_name
        'homework' : list of floats for homework grades
        'quizzes'  : list of floats for quiz grades
        'tests'    : list of floats for test grades
        """
        d = student_dict
        return cls(d['name'], d['homework'], d['quizzes'], d['tests'])

    def __str__(self):
        """
        Returns a string representation of the current
        object. The representation will be in the form
        of the fields separated by the default separator
        character (currently '|').
        """
        conv = lambda x, d: d.join(map(str, x))
        sep  = self.delimiter

        buff = ''
        buff +=      self.__name           + sep
        buff += conv(self.__homework, sep) + sep
        buff += conv(self.__quizzes,  sep) + sep
        buff += conv(self.__tests,    sep) 

        return buff

    def __repr__(self):
        """
        Returns a representation of the current object. In this
        case, we will return the same thing as __str__
        """
        return str(self)


    def to_dict(self):
        """
        Returns a dict representation of this object containing
        the keys ['name', 'homework', 'quizzes', 'tests'] where
        homework, quizzes, and tests are lists of floats.
        """
        obj = {}
        obj['name']     = self.__name
        obj['homework'] = self.__homework
        obj['quizzes']  = self.__quizzes
        obj['tests']    = self.__tests
        return obj



    def get_student_average(self, tuplify=False):
        """
        This method retrieves the student's class average according
        to predefined weighting rules. In this method, we average the
        list of scores together for the student's homework, quizzes,
        and tests, multiply them by their respective weights, and
        sum them together to obtain the final score. See implementation
        for more details.
        """
        hw = self.__homework
        qu = self.__quizzes
        ts = self.__tests

        if(0 not in map(len, [hw, qu, ts])): #division by zero, bla bla
            avg  = lambda l: sum(l)/len(l)
            avgs = map(avg,  [hw, qu, ts])
            hwa  = avgs[0] * Student.homework_weight
            qua  = avgs[1] * Student.quiz_weight
            tsa  = avgs[2] * Student.test_weight
            if tuplify is False:
                return sum([hwa, qua, tsa])
            else: 
                return (hwa, qua, tsa)

    def get_student_averages(self):
        """
        This method retrieves the student's class averages according
        to predefined weighting rules. In this method, we average the
        list of scores together for the student's homework, quizzes,
        and tests, multiply them by their respective weights, and return
        a set of them as a tuple where (homeworka, quiza, testa)
        See implementation for more details. 
        """
        return self.get_student_averages(tuplify=True)

    def get_student_letter_grade(self):
        """
        This method takes a student's letter score according to their
        average (computed by self.get_student_average()) and fetches
        the appropriate letter grade (A through F)
        """
        score = self.get_student_average()
        if   score >= 90:   return 'A'
        elif score >= 80:   return 'B'
        elif score >= 70:   return 'C'
        elif score >= 60:   return 'D'
        else:           return 'F'

    @staticmethod
    def __get_significant_average(grade_list):
        """ 
        Takes a list of grades and returns an average, does the average
        using proper significant figures according to a global variable
        grade_list -- a list of floats to average
        """
        sigfig = lambda x, n: round(x, -int(floor(log10(x))) + (n - 1))
        avg    = sigfig(sum(grade_list)/len(grade_list), num_figs)
        print '\t\t' + str(avg)
        return avg

    @staticmethod
    def get_class_set(student_list):
        """
        Generates a student object from a list of students
        and by assembling all the student's grades for each
        assignment and then using methods in the Student class
        to compute what we need to compute. 
        """
        # this is REALLY slick. What we're going to do is create a 
        # generator  generators of the student's homework and test
        # grades, but for the quizzes we will make regular list of
        # lists. 
        hwg = (x.get_homeworks()            for x in student_list)
        qwg = [[q for q in y.get_quizzes()] for y in student_list]
        twg = (z.get_tests()                for z in student_list)

        tl = lambda l: [x for x in l]
        # ^This is a lambda expression that converts a generator l
        # to a list (hence tl)



        # since each get_blabla() function returns a generator
        # and since each *wg variable is a generator of a generator
        # we will eventually get sublists of sublists of sublists
        # on and on and on and need to flatten them. Here are three
        # ways to do that. 
    # http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python 
        hwl = [item for sublist in hwg for item in sublist]
        qwl = sum(qwg, []) 
        twl = reduce(lambda x,y: tl(x)+tl(y), twg)

        class_set = Student('class_whole_set', hwl, qwl, twl)
        return class_set




if __name__ == "__main__":

    lloyd = {
        "name": "Lloyd",
        "homework": [90.0, 97.0, 75.0, 92.0],
        "quizzes": [88.0, 40.0, 94.0],
        "tests": [75.0, 90.0]
    }

    alice = {
        "name": "Alice",
        "homework": [100.0, 92.0, 98.0, 100.0],
        "quizzes": [82.0, 83.0, 91.0],
        "tests": [89.0, 97.0]
    }

    tyler = {
        "name": "Tyler",
        "homework": [0.0, 87.0, 75.0, 22.0],
        "quizzes": [0.0, 75.0, 78.0],
        "tests": [100.0, 100.0]
    }

    slloyd  = Student.from_dict(lloyd)
    salice  = Student(alice['name'], alice['homework'], alice['quizzes'], alice['tests'])
    styler  = Student.from_dict(tyler)

#  YOU COULD DO THIS!
#   print 'lloyd dict'
#   print '\t' + str(sdlloyd)
#
#   print 'alice ctor'
#   print '\t' + str(slloyd)
#
#   print 'slloyd name: ' + slloyd.to_dict()['name']
#   print 'slloyd home: ' + str(map(str, slloyd.to_dict()['homework']))
#   print 'slloyd quiz: ' + str(map(str, slloyd.to_dict()['quizzes']))
#   print 'slloyd test: ' + str(map(str, slloyd.to_dict()['tests']))
#   print 'slloyd avg:  ' + str(slloyd.get_student_average())
#
#   conv = lambda x: str(map(str, x))
#   print 'salice name: ' + salice.get_name()
#   print 'salice home: ' + conv(salice.get_homeworks())
#   print 'salice quiz: ' + conv(salice.get_quizzes())
#   print 'salice test: ' + conv(salice.get_tests())
#   print 'salice avg:  ' + str(salice.get_student_average())
#


    """Unit test some object obj"""
    def unit_test(objname, obj):
        conv = lambda x: str(map(str, x))
        print str(objname) + ' name: ' + obj.get_name()
        print str(objname) + ' home: ' + conv(obj.get_homeworks())
        print str(objname) + ' quiz: ' + conv(obj.get_quizzes())
        print str(objname) + ' test: ' + conv(obj.get_tests())
        print str(objname) + ' avg : ' + str(obj.get_student_average())
        print str(objname) + ' let : ' + obj.get_student_letter_grade()

    sclss  = Student.get_class_set( [slloyd, salice, styler] )
    unit_test('sclss', sclss)
    unit_test('slloyd', slloyd)
    unit_test('salice', salice)
    unit_test('styler', styler)

如果这对你有帮助,或者你对代码的某个部分感到困惑,请告诉我。欢迎来到Stack Overflow :)

撰写回答