つくる 入力検証の例外設計
このレッスンでできるようになること。この章で覚えた道具だけを使い、家計簿の取り込み処理を「下の層で投げて、上の層で受け止める」形に組み上げられるようになります。新しい概念は足しません。
エラー処理の設計で一番大事なのは、投げる場所と受け止める場所を分けることです。データを 1 件ずつ見る検証関数は、おかしいと思ったら例外を投げるだけにします。何件処理したか、どこで止めるかを決めるのは、まとめ役の関数の仕事です。この分け方をしておくと、検証の規則を足すときに、まとめ役へ手を入れずに済みます。
型名は type(value).__name__ で文字列として取り出せます。整数の型名は "int"、リストは "list" なので、文字列の比較で確かめられます。
Python
count = 12
labels = ["未読", "既読"]
print(type(count).__name__ == "int") # True
print(type(labels).__name__ == "list") # True今回組み上げるのは次の流れです。まず assert で、そもそも受け取った引数の形が正しいかを確かめます。次に 1 件ずつ検証関数へ渡し、InvalidExpenseError を受け止めて不備の一覧に貯めます。例外が出なかった件だけを受理します。最後に合計と予算を比べ、超えていれば BudgetOverError を投げて自分で受け止め、finally の節で処理の記録を残します。
Python
class InvalidExpenseError(Exception):
passこのように、この章で書いた raise、カスタム例外、else、finally、assert を、役割ごとの関数に分けて組み合わせます。演習では、型の前提を assert で確かめる部分、金額の型が違うときに投げる部分、それをまとめ役が受け止める部分を書きます。品名や負の金額の検査、受理した品名の記録、予算の判定と結果の整形は準備済みです。補助関数の説明を読み、投げる側と受け止める側の役割をつなげてください。
要件
- 用意済みの InvalidExpenseError と BudgetOverError を使う。品名の空欄と負の金額の検査は prepare_expense が行う
- validate で type(amount).name を "int" と比べ、整数でなければ InvalidExpenseError で 品名 の金額が数値ではありません を投げる
- import_expenses の最初の try 内で、type(records).name を "list" と比べて assert する。メッセージは records はリストで渡してください とする
- 各 record の処理に try と except InvalidExpenseError as e を書き、validate の戻り値を amount に入れる。不備は errors に str(e) を追加して次へ進む
- 検証できたら accept_expense(record, amount, accepted) の戻り値を total に足す。この補助関数は品名を accepted に追加し、金額を返す
- 前提違反の結果と、予算の判定、finally による記録、返す辞書の整形は用意済みの処理を使う