你不是真的应该取平均值,只是为了让你知道。我已更正您的代码以使其正常工作。那就是:
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的各种功能,包括文档字符串,发电机,列表内涵,类,以及map-reduce模式,还有一些新的导入以及如何对模块进行单元测试。我知道你说过要对你的代码做最小的修改,但是我觉得简单地解决你的问题并继续前进将会是一种不礼貌的行为。我想给你一些片段,使用你的例子,我自己学习python时建立和学习。
我的例子比你的例子更长更大,我不建议你采用最短最简单的路线,我只是提供一个例子。当你阅读这些内容时,不要惊慌,只要仔细阅读并使用它,并尽可能利用它。在它开始有意义之前,您可能必须保持一段时间在您的头文件系统中反复思考。
如果你想知道垃圾的全部内容,我建议你将我的代码保存在一个名为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)
请让我知道这是否有助于您,如果您对此代码的任何方面感到困惑。欢迎堆栈溢出:)
你应该通过以前的功能,并试图了解他们首先是如何工作的。 –
在get_class_average中,当您应该迭代学生时,您正在迭代结果(空列表)。 '给学生的学生:' 也把回路放在for循环之外 - 否则它只会返回第一个学生。 这应该为你解决它。 – Jordan
Ignacio Vazquez-Abrams我明白他们是如何工作的,我一个接着一个一个地写了以前的功能。在最后一个函数中,我显然错过了一些东西 –