評分

評分

學習練習

簡介

Python 有兩種迴圈結構。 while迴圈用於_不確定_(不計數)的疊代,for迴圈則用於_確定_(計數)的疊代。 關鍵字break、continue和else可以幫助你自訂迴圈的行為。 range()和enumerate()則能協助處理迴圈的計數與索引。

while 迴圈

while迴圈只要loop expression或「test」在 boolean context中評估為True,就會持續執行,直到評估為False時終止:


# Lists are considered "truthy" in a boolean context if they
# contain one or more values, and "falsy" if they are empty.

>>> placeholders = ["spam", "ham", "eggs", "green_spam", "green_ham", "green_eggs"]

>>> while placeholders:
...     print(placeholders.pop(0))
...
'spam'
'ham'
'eggs'
'green_spam'
'green_ham'
'green_eggs'

for 迴圈

Python 裡最基本的 for loop,更貼切的說法是 for each:它會逐一走訪任何可疊代物件的值,並在呼叫 next()不再回傳任何值時結束:


>>> word_list = ["bird", "chicken", "barrel", "bongo"]

>>> for word in word_list:
...    if word.startswith("b"):
...        print(f"{word.title()} starts with a B.")
...    else:
...        print(f"{word.title()} doesn't start with a B.")
...
'Bird starts with a B.'
'Chicken doesn\'t start with a B.'
'Barrel starts with a B.'
'Bongo starts with a B.'

序列物件 range()

如果沒有指定特定的iterable,就會使用特殊的 range()序列來當作迴圈計數器。 range()需要一個int來指定序列的stop位置,也可以選擇性地接收start和step參數。 如果沒有提供start數字,序列就會從 0 開始。 range()物件是惰性的(值會在需要時才產生),支援所有常見序列操作,而且無論指定的序列有多長,佔用的記憶體都是固定的。

# Here we use range to produce some numbers, rather than creating a list of them in memory.
# The values will start with 1 and stop *before* 7

>>> for number in range(1, 7):
...    if number % 2 == 0:
...       print(f"{number} is even.")
...    else:
...       print(f"{number} is odd.")
'1 is odd.'
'2 is even.'
'3 is odd.'
'4 is even.'
'5 is odd.'
'6 is even.'

# range() can also take a *step* parameter.
# Here we use range to produce only the "odd" numbers, starting with 3 and stopping *before* 15.

>>> for number in range(3, 15, 2):
...    if number % 2 == 0:
...       print(f"{number} is even.")
...    else:
...       print(f"{number} is odd.")
...
'3 is odd.'
'5 is odd.'
'7 is odd.'
'9 is odd.'
'11 is odd.'
'13 is odd.'

使用 enumerate() 取值與索引

如果需要同時取得值和索引,內建的 enumerate(<iterable>)會回傳(index、value)配對:


>>> word_list = ["bird", "chicken", "barrel", "apple"]

# *index* and *word* are the loop variables.
# Loop variables can be any valid python name.

>>> for index, word in enumerate(word_list):
...    if word.startswith("b"):
...        print(f"{word.title()} (at index {index}) starts with a B.")
...    else:
...        print(f"{word.title()} (at index {index}) doesn't start with a B.")
...
'Bird (at index 0) starts with a B.'
'Chicken (at index 1) doesn\'t start with a B.'
'Barrel (at index 2) starts with a B.'
'Apple (at index 3) doesn\'t start with a B.'


# The same method can be used as a "lookup" for pairing items between two lists.
# Of course, if the lengths or indexes don't line up, this doesn't work.

>>> word_list = ["cat", "chicken", "barrel", "apple", "spinach"]
>>> category_list = ["mammal", "bird", "thing", "fruit", "vegetable"]

>>> for index, word in enumerate(word_list):
...    print(f"{word.title()} is in category: {category_list[index]}.")
...
'Cat is in category: mammal.'
'Chicken is in category: bird.'
'Barrel is in category: thing.'
'Apple is in category: fruit.'
'Spinach is in category: vegetable.'

改變迴圈行為

continue關鍵字可以讓你跳過目前這一輪,直接進入下一個疊代:

word_list = ["bird", "chicken", "barrel", "bongo", "sliver", "apple", "bear"]

# This will skip *bird*, at index 0
for index, word in enumerate(word_list):
    if index == 0:
        continue
    if word.startswith("b"):
        print(f"{word.title()} (at index {index}) starts with a b.")

'Barrel (at index 2) starts with a b.'
'Bongo (at index 3) starts with a b.'
'Bear (at index 6) starts with a b.'

break(就像許多與 C 相關的語言一樣)關鍵字可以用來停止疊代,並從最內層的loop中「跳出」:

>>>  word_list = ["bird", "chicken", "barrel", "bongo", "sliver", "apple"]

>>> for index, word in enumerate(word_list):
...    if word.startswith("b"):
...        print(f"{word.title()} (at index {index}) starts with a B.")
...    elif word == "sliver":
...       break
...    else:
...       print(f"{word.title()} doesn't start with a B.")
... print("loop broken.")
...
'Bird (at index 0) starts with a B.'
'Chicken doesn\'t start with a B.'
'Barrel (at index 2) starts with a B.'
'Bongo (at index 3) starts with a B.'
'loop broken.'

說明

你是負責批改學生考卷的助教。 手動記錄成績既繁瑣又容易出錯。 你決定寫一些函式來統計和計算全班的成績,讓這件事變得有趣一點。

1. 分數四捨五入

雖然考試題目可以給「部分分數」,但整體考試成績必須是 int。 所以在對全班成績做任何其他處理之前,你需要先檢查所有成績,把任何 float 分數轉成 int。幸好 Python 有內建的 round() 函式可以用。

建立函式 round_scores(student_scores),它接收 student_scores 這個 list。 這個函式應該 消耗 輸入的 list,並 return 一個新 list,其中所有分數都轉成 int。 產生的 list 中,分數的順序不重要。

>>> student_scores = [90.33, 40.5, 55.44, 70.05, 30.55, 25.45, 80.45, 95.3, 38.7, 40.3]
>>> round_scores(student_scores)
...
[40, 39, 95, 80, 25, 31, 70, 55, 40, 90]

2. 不及格的學生

在批改考試時,你注意到有些學生的表現不如你預期。 但你分了心,忘記確切記下 有多少 學生。

建立函式 count_failed_students(student_scores),它接收 student_scores 這個 list。 這個函式應該計算沒有達到及格分數的學生人數,並以整數回傳該數量。 學生需要在考試中拿到高於 40 的分數才能及格。

>>> count_failed_students(student_scores=[90,40,55,70,30,25,80,95,38,40])
5

3. 「最佳」

你協助的老師想找出在這場考試中表現「最佳」的一群學生。 所謂「最佳」的標準會變動,所以你需要找出大於或等於目前門檻的學生成績。

建立函式 above_threshold(student_scores, threshold),以 student_scores(成績的 list)和 threshold(「最高分」門檻)作為參數。 這個函式應該回傳所有 >= threshold 的分數所組成的 list。

>>> above_threshold(student_scores=[90,40,55,70,30,68,70,75,83,96], threshold=75)
[90,75,83,96]

4. 計算等第成績

你協助的老師喜歡同時給等第成績和數值分數。 由於學生很少在考試中拿到 100 分,「等第」的下限門檻會根據最高分計算,並在最高分與 <= 40 的不及格門檻之間平均遞增。

建立函式 letter_grades(highest),以考試中的「最高」分作為引數,並回傳每個「美式」等第區間的分數下限門檻所組成的 list:["D", "C", "B", "A"]。

"""Where the highest score is 100, and failing is <= 40.
       "F" <= 40
 41 <= "D" <= 55
 56 <= "C" <= 70
 71 <= "B" <= 85
 86 <= "A" <= 100
"""

>>> letter_grades(highest=100)
[41, 56, 71, 86]


"""Where the highest score is 88, and failing is <= 40.
       "F" <= 40
 41 <= "D" <= 52
 53 <= "C" <= 64
 65 <= "B" <= 76
 77 <= "A" <= 88
"""

>>> letter_grades(highest=88)
[41, 53, 65, 77]

5. 將姓名與分數配對

你有一份依降序排列的考試分數陣列,還有一份學生姓名陣列,同樣依他們的考試分數降序排列。 你想把每位學生的姓名與其考試分數配對,並印出全班的整體排名。

建立函式 student_ranking(student_scores, student_names),參數為 student_scores 和 student_names。 將 student_names list 中的每個學生姓名與 student_scores list 中對應的分數配對。 你可以假設每個引數 list 都會從最高分(者)排到最低分(者)。 這個函式應該回傳一個字串 list,格式為 <rank>. <student name>: <student score>。

>>> student_scores = [100, 99, 90, 84, 66, 53, 47]
>>> student_names =  ['Joci', 'Sara','Kora','Jan','John','Bern', 'Fred']
>>> student_ranking(student_scores, student_names)
...
['1. Joci: 100', '2. Sara: 99', '3. Kora: 90', '4. Jan: 84', '5. John: 66', '6. Bern: 53', '7. Fred: 47']

6. 「完美」的分數

雖然考試中要拿到 100 分的「完美」成績很罕見,但知道是否至少有一位學生達成仍很有意思。

建立函式 perfect_score(student_info),參數為 student_info。 student_info 是一個由 list 組成的 list,包含每位學生的姓名和分數:[["Charles", 90], ["Tony", 80]]。 這個函式應該 return 考試中拿到 100 分的學生中 第一組 [<name>, <score>] 配對。

如果在 student_info 中找不到 100 分,就應該回傳一個空的 list []。

>>> perfect_score(student_info=[["Charles", 90], ["Tony", 80], ["Alex", 100]])
["Alex", 100]

>>> perfect_score(student_info=[["Charles", 90], ["Tony", 80]])
[]
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Python Exercism

準備好開始 評分 了嗎?

註冊 Exercism,透過 17 個概念146 個練習 和真人引導來學習並精通 Python,全部免費。