註釋

已完成

若要了解如何建置參考實作,我們必須先查看參考實作的建置區塊:註釋。 註釋是講師針對每個提交所建立的 Python 物件,用於判斷提示條件;這些條件可以是值是否存在、值之間的時態關聯性,或甚至是程式碼區塊的時間複雜度等專案。 您可以藉由具現化 pybryt 封裝所提供的類別來建立註釋。

主要有三種註釋類型:

  • 值註釋,判斷學生記憶體使用量中有某些值存在
  • 關聯式註釋,判斷學生記憶體使用量中的值之間關聯性,這些值可在布林邏輯或時態性中找到
  • 複雜度註釋,判斷程式碼區塊上的時間複雜度

在本課程模組中,我們將討論第一種類型。

值註釋

值註釋判斷學生磁碟使用量中有某值存在。 這些註釋是由具現化類別 pybryt.Value 所建立,並會採用您想要尋找的值作為其唯一的位置引數。

例如,假設您想要檢查學生是否已正確初始化陣列。 在參考實作中,您會初始化陣列,然後建立以下類別的執行個體:

>>> np.random.seed(42)
>>> arr = np.random.normal(size=(100,100))
>>> pybryt.Value(arr)
pybryt.Value

PyBryt 會追蹤您建立的所有註釋,因此除非您想要使用這些註釋來建立更複雜的註釋,否則不需要將它們指派給變數。

值註釋在用於檢查數值 (包括陣列、可反覆運算的數字和 DataFrame ) 時,也支援使用 atolrtol 引數的絕對和相對容錯:

>>> value_annotation = pybryt.Value(arr, atol=1e-3)
>>> value_annotation.check_against(arr.round(3)), value_annotation.check_against(arr.round(2))
(True, False)

方法 pybryt.Value.check_against 會傳回布林值,指出傳遞給其的物件是否符合值註釋。 如前所示,藉由允許 $10^{-3}$ 的絕對容錯,當陣列值四捨五入為小數第三位時,就會滿足此值,但在四捨五入至小數第二位時失敗。

等價函式

雖然 Value 物件會定義演算法來判斷兩個物件是否相等,但也允許使用者指定要用於比較的自訂等價函式。 例如,假設您想要在學生的程式碼中尋找字串,但對於該字串的大小寫並不介意。 您可以使用自訂等價函式,來比較兩個字串的小寫標記法:

def str_equal_lower(s1, s2):
    return s1.lower() == s2.lower()

然後,我們可以使用此函式來建立 Value 註釋以檢查十六進位字串,例如:

>>> message = "hash me"
>>> sha1_hash = hashlib.sha1(message.encode()).hexdigest()
>>> sha1_annotation = pybryt.Value(sha1_hash, equivalence_fn=str_equal_lower)
>>> sha1_annotation.check_against(sha1_hash.upper())
True

註釋選項

所有註釋都支援選項,可讓您量身打造學生在達成或未達成這些註釋時收到的意見反應。 提供此意見反應的兩個主要方法是使用建構函式中的 success_messagefailure_message 引數,可供所有註釋使用:

v = pybryt.Value(1, success_message="Found 1!", failure_message="Didn't find 1 :(")

如果在學生的磁碟使用量中找到此值,則 success_message 會包含在 PyBryt 學生實作檢查程式所產生的報表中;如果找不到,則會包含 failure_message。 如果未提供這些引數,則不會顯示任何訊息。

您也可以藉由更新註釋物件中對應的具名欄位來設定這些訊息:

v.success_message = "Congrats!"
v.failure_message = "Try again"

集合註釋

關聯式註釋的最基本類型是集合註釋,只會一起收集一組批註,以將其當作單位運作。 您可以 (根據插入順序) 強制執行集合中註釋的順序 ,但此強制執行是選擇性的。 如同所有其他註釋,可以根據集合是否滿足使用 success_messagefailure_message 引數來提供意見反應。

若要建立集合,請具現化 pybryt.Collection。 建構函式會接受任意數目的位置引數,這些引數會對應至集合中的初始註釋集。 若要初始化空集合,請提供無位置引數。

col = pybryt.Collection(pybryt.Value(1))

若要強制執行集合中註釋的順序,請傳遞 enforce_order=True

col = pybryt.Collection(pybryt.Value(1), enforce_order=True)

註釋可以使用 pybryt.Collection.add 新增至集合:

col.add(pybryt.Value(2))

滿足註釋集合的情況如下:當滿足其所有子系,且 enforce_order 為 true,且符合其子系以非遞減順序發生的時間戳記時。 例如,讓我們針對 col 檢查兩個記憶體使用量:一個是在 2 之前發生 1,另一個是在 1 之前發生 2。

>>> col.check(pybryt.MemoryFootprint.from_values(1, 1, 2, 2)), col.check(pybryt.MemoryFootprint.from_values(2, 1, 1, 2))
(AnnotationResult(satisfied=True, annotation=pybryt.Collection),
 AnnotationResult(satisfied=False, annotation=pybryt.Collection))

註釋集合可用於將註釋分組在一起,代表提供一致意見反應的問題部分。 例如,如果您要撰寫用來加總數字清單的參考,可以將每個部分總和的註釋放入具有自己成功和失敗訊息的集合中。 學生接下來可在其意見反應中取得單一訊息,以驗證總和。 您也可以使用此集合來強制執行清單上的反復專案順序,以確保學生的順序正確。

除了集合之外,還有其他數種類型的關聯式註釋。 您可在進階 PyBryt 課程模組中深入了解。

檢定您的知識

1.

哪種類型的註釋會檢查學生記憶體使用量中是否有特定值?

2.

下列哪一個呼叫會為值清單建立值註釋,並忽略清單的順序?

3.

關於強制執行其子系順序的集合註釋預設行為為何?