Day26 Dictionary Comprehension 問題

代碼如下:

import random

names = ['Alex' , 'Beth', 'Caroline', 'Dave', 'Eleanor', 'Freddie']     #宣告並定義六名學生名字清單

scores = {student: random.randint(1,100) for student in names}   #隨機產生成績並生成dict,名字:成績

print(scores)

passed_student = {a:b for (students,score1) in scores.items() if score1 > 60} #找出分數大於60分的學生,並生成dict

print(passed_student)

針對此行代碼(上面代碼的倒數第二行)

passed_student = {a:b for (students,score1) in scores.items() if score1 > 60}

測試時有發現以下現象:

1.當隨機產生成績至少有一個學生成績大於60分(滿足if判斷式)會出現

NameError: name 'b' is not defined

2.當隨機產生成績都在60分以下時(皆不滿足if判斷式,此部分可修改成績範圍來偷吃步),不會報錯,而是返回{}
想請教背後的原因,感謝

PS 如果在描述問題的部分用詞不夠精準,例如返回、宣告、定義等專業術語,也歡迎點出並指教,謝謝

我剛開始上 Day 9,剛好是 Dictionary,所以只能看看和老師的解法哪裡不同。
我參考你的變數命名,以這兩種方式寫。參考一下,謝謝!

passed_student = {a:score1 for (a,score1) in scores.items() if score1 > 60}

passed_student = {students:score1 for (students,score1) in scores.items() if score1 > 60}

2的部分,我覺得是變數設定它的值時,就決定了它的資料型態。
即使沒有符合的值被加進去,資料型態還是對的。
可以加一行 print(type(valuable)) 來確認它的資料型態

passed_student = {students:score1 for (students,score1) in scores.items() if score1 > 90}

print(type(passed_student)) # 查看資料型態,結果是 <class 'dict'> 無誤

print(passed_student)

嗨~
剛剛稍微看過你的程式碼了, 稍微分享一下我的看法給你:

第一個問題

首先解釋一下你第一個問題是出在你變數用錯了, 可以參考上面版大的解決方法選擇用其中一種, 會發生這樣的情形建議可以多看一下 Dictionary Comprehension 的語法。 超過 60 分後會發生 Not defined 的原因是因為 Python interpreter 會去先檢查你的 if 條件 score1>60 ,檢查確認的確有達成後它會把你寫在最前面的 a:b 這組 key-value 加到passed_student 裡頭,

總結檢查步驟為:

  1. 判斷 score1 是否為大於 60 分, 是的話進入第2步驟;否的話不會進行第2步驟
  2. 將 a:b 加入 passed_student

大於 60 後的錯誤訊息表示在第二步驟時直譯器發現在這個區塊裡頭找不到 a 與 b 兩個變數, 因此發生這個錯誤訊息。

第二個問題

算是可以銜接第一個問題, 在分數全都 60 分以下時不會有錯誤的原因是因為它不會執行上面第一個問題中提到的把你寫在最前面的 a:b 這組 key-value 加到passed_student 裡頭這個動作, 也就是說它在第一步驟時就跳開了, 然而錯誤訊息是因為第二步驟才導致的, 因此不會有錯誤訊息

至於為什麼 passed_student = {} 其實很簡單, 在我們寫出下列這行時無論有沒有新的 key-value 被放進來, passed_student 本身都是 empty Dictionary, 也就是 {} 的樣子

passed_student = {a:b for (students,score1) in scores.items() if score1 > 60}

如果還是不懂的話還原一下這個寫法原本的樣子, 不採用 Dictionary Comprehension 的寫法會長這樣:

student = {
    "Amy": 13,
    "Boy": 59,
    "Cindy": 43
}

pass_student = {}
for (name,score) in student.items():
    if(score>=60):
        pass_student[name] = score

在一開始時我們就先設定好 pass_student 是 {} 對吧, 後續要加入成員得先經過條件判斷, 因此如果條件通通不成立那結果當然會是空的

希望有幫忙到你~

4個讚

太感謝了,說明的好清楚。
我們論壇愈來愈像我想像中的樣子了。

清楚了,感謝:pray: