2017-04-15 47 views
1
def print_report_card(report_student = None): 
    for student in students: 
     if (student[0] == report_student) or (report_student == None): 
      print("Report card for student ", student[0])    
      for subject, mark in student[1].items(): 
       for grade in grades: 
        if mark < grade[0]: 
         print(subject, " : ", prev_grade) 
         break 
        prev_grade = grade[1] 

努力理解這個片段:使用「學習Python與Raspberry Pi」來自Wiley prev_grade從哪裏來?

for grade in grades: 
    if mark < grade[0]: 
     print(subject, " : ", prev_grade) 
     break 
    prev_grade = grade[1] 

等級是元組

grades = ((0, "FAIL"),(50, "D"),(60,"C"),(70, "B"), (80," A"), (101, "CHEAT!")) 和學生的元組列表的使用詞典

students = [["Ben", {"Maths": 67, "English": 78, "Science": 72}], 
      ["Mark", {"Maths": 56, "Art": 64, "History": 39, "Geography": 55}], 
      ["Paul", {"English": 66, "History": 88}]] 

但不知道名單prev_grade位來自哪裏以及它如何工作,有什麼幫助?

+0

如果其中一個答案解決了您的問題,您應該接受它(單擊相應答案旁邊的複選標記)。這有兩件事。它讓每個人都知道你的問題已經得到解決,讓你滿意,並且它可以幫助你幫助你。請參閱[此處](http://meta.stackexchange.com/a/5235)以獲取完整說明。 –

回答

0

prev_grade爲立體字符串是在

for grade in grades: 

循環的前一次迭代中。當我們第一次進入該循環時,grade被設置爲(0, "FAIL"),因此grade[0]爲零。而且由於mark總是> = 0下面的測試

if mark < grade[0]: 

不能是真實的,所以我們沒有進入if塊,所以它並不重要prev_grade尚不存在因爲我們不打算在循環的這個迭代中打印它。所以我們跳過了if塊來

prev_grade = grade[1] 

這臺prev_grade因此它可以在下一輪for循環使用。我們需要prev_grade,因爲我們不知道等級是什麼,直到我們看到一個grade元組的grade[0]大於mark,然後我們知道正確的等級字符串是來自先前的grade元組的字符串。

真正理解發生了什麼的最好方法是在紙上手動「執行」代碼。假裝你是Python解釋器,並按照代碼中的說明操作,看看會發生什麼。

但是如果你沒有耐心做,它可以幫助你添加了一些額外的打印語句代碼,就像這樣:

grades = (
    (0, "FAIL"), 
    (50, "D"), 
    (60,"C"), 
    (70, "B"), 
    (80, "A"), 
    (101, "CHEAT!") 
) 

students = [ 
    ["Ben", {"Maths": 67, "English": 78, "Science": 72}], 
    ["Mark", {"Maths": 56, "Art": 64, "History": 39, "Geography": 55}], 
    ["Paul", {"English": 66, "History": 88}], 
] 

def print_report_card(report_student=None): 
    for student in students: 
     if (student[0] == report_student) or (report_student is None): 
      print("\nReport card for student ", student[0]) 
      for subject, mark in student[1].items(): 
       print('\nSUBJECT', subject, 'MARK', mark) 
       for grade in grades: 
        print('GRADE', grade) 
        if mark < grade[0]: 
         print(subject, " : ", prev_grade) 
         break 
        print('SETTING prev_grade TO', grade[1]) 
        prev_grade = grade[1] 

print_report_card("Paul") 

輸出

Report card for student Paul 

SUBJECT English MARK 66 
GRADE (0, 'FAIL') 
SETTING prev_grade TO FAIL 
GRADE (50, 'D') 
SETTING prev_grade TO D 
GRADE (60, 'C') 
SETTING prev_grade TO C 
GRADE (70, 'B') 
English : C 

SUBJECT History MARK 88 
GRADE (0, 'FAIL') 
SETTING prev_grade TO FAIL 
GRADE (50, 'D') 
SETTING prev_grade TO D 
GRADE (60, 'C') 
SETTING prev_grade TO C 
GRADE (70, 'B') 
SETTING prev_grade TO B 
GRADE (80, 'A') 
SETTING prev_grade TO A 
GRADE (101, 'CHEAT!') 
History : A 

可以爭辯說,在它之前沒有定義的情況下,在if塊中引用prev_grade的方式很糟糕。當然,我的分析表明它是安全的,它不應該讓有經驗的編碼員感到困惑,但它仍然會讓你放慢閱讀這些東西的速度。這將是很多更好(恕我直言)定義prev_grade以外的循環,或至少有解釋發生了什麼評論。或者做兩個。 :)

for subject, mark in student[1].items(): 
    prev_grade = None 
    for grade in grades: 
     # This condition can never be True on the first loop iteration 
     if mark < grade[0]: 
      print(subject, " : ", prev_grade) 
      break 
     prev_grade = grade[1] 

您可能注意到,我改變(report_student == None)(report_student is None),後者是更有效和Python的風格指南,PEP-0008的建議。

+1

感謝您的解釋,現在您指出在for循環中if標記 Dion

0

IMO此代碼是不必要的複雜。它依賴於一個事實,即if mark < grade[0]總是在第一次迭代假的,因爲第一項從grades

grades = ((0, "FAIL"),(50, "D"),(60,"C"),(70, "B"), (80," A"), (101, "CHEAT!")) 

grades[0]0。並且students中的每個數字都大於0。所以if體被跳過,我們得出:

prev_grade = grade[1] 
它循環並進入 if體下一次

所以,prev_grade將被定義。如果有等級小於0:

In [3]: students = [["Ben", {"Maths": -1, "English": 78, "Science": 72}], 
    ...:    ["Mark", {"Maths": 56, "Art": 64, "History": 39, "Geography": 55}], 
    ...:    ["Paul", {"English": 66, "History": 88}]] 
    ...: 

現在我們嘗試調用函數:

In [4]: print_report_card() 
Report card for student Ben 
--------------------------------------------------------------------------- 
UnboundLocalError       Traceback (most recent call last) 
<ipython-input-6-aa68f0bb7206> in <module>() 
----> 1 print_report_card() 

<ipython-input-2-9f9e72e91ef4> in print_report_card(report_student) 
     6     for grade in grades: 
     7      if mark < grade[0]: 
----> 8       print(subject, " : ", prev_grade) 
     9       break 
    10      prev_grade = grade[1] 

UnboundLocalError: local variable 'prev_grade' referenced before assignment 

,我們得到了UnboundLocalError你所期望的。

+0

謝謝,我明白這一點,並再次分配價值在第一次使用會阻止這一點。 – Dion

0

的prev_grade被用於記住先前級[1]這是在if語句輸入代碼之前檢查:

if mark < grade[0]: 
     print(subject, " : ", prev_grade) 
break 

如果級別值是更大的if語句的代碼將被執行比標記值。當數值大於標記時表示前一個數值是學生收到的成績數值。

如果您輸入當前等級[1]時輸入if語句,則顯示的等級值是錯誤的值,因爲它的一個等級值大。您可以通過在代碼中將「prev_grade」更改爲「grade [1]」來在代碼中對此進行測試。打印值時,您會看到對於等級[0]值「67」,所需值「C」改爲值「B」。

+0

感謝您的回答 – Dion