2014-07-05 186 views
1

我想學習Python,並且卡住了。一切都很正常,直到最後一個函數是:在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) 
+0

你應該通過以前的功能,並試圖瞭解他們首先是如何工作的。 –

+0

在get_class_average中,當您應該迭代學生時,您正在迭代結果(空列表)。 '給學生的學生:' 也把迴路放在for循環之外 - 否則它只會返回第一個學生。 這應該爲你解決它。 – Jordan

+0

Ignacio Vazquez-Abrams我明白他們是如何工作的,我一個接着一個一個地寫了以前的功能。在最後一個函數中,我顯然錯過了一些東西 –

回答

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的各種功能,包括文檔字符串,發電機,列表內涵,類,以及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) 

請讓我知道這是否有助於您,如果您對此代碼的任何方面感到困惑。歡迎堆棧溢出:)

+0

非常感謝您的回答。我仍在研究你的第二個答案的更長示例代碼,這確實非常複雜。我非常感激。然而,第一個簡單的版本仍然沒有返回我正在尋找的東西。我試圖用最後一個函數get_class_average得到的結果是,首先使用函數get_average()獲取每個學生的平均值,以某種方式將結果附加到結果中,最後返回平均類,即每個學生的平均值,通過使用函數average()。請讓我知道你的想法。 –

+0

你太受歡迎了。如果我的回答很有幫助,請不要忘記標記爲答案。一旦你全面追蹤,我的第二部分代碼並不複雜 - 我的建議是將它打印出來並用筆和紙手工追蹤。此外,簡單版本的get_class_average完全符合您的說法;即使從技術上來說,平均數是一種不正確的做法。你得到的結果是你不喜歡的? – alvonellos

+0

@ alvonellos我編輯了我的原始問題併發布瞭解決方案。請參閱我上面的編輯。 –

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 = float(sum(numbers)) return total/len(numbers)

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

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

students = [lloyd,alice,tyler]

def get_class_average(students): results = [] for student in students: print "student: %s, srednia %s" % (student['name'],get_average(student)) results.append(get_average(student)) print results print get_average(student) return average(results)

print get_class_average(students)

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))