close を書き忘れる
開いたまま放置するとファイルが解放されず、書き込んだ内容が反映されないことがあります。次のレッスンで学ぶ with を使えばこの問題は消えます。
レッスンの本文で注意している点を、つまずきの側から30件ぶん並べ直しました。書いた覚えのある形が見つかったら、 そのままレッスンに戻って前後を読めます。
close を書き忘れる開いたまま放置するとファイルが解放されず、書き込んだ内容が反映されないことがあります。次のレッスンで学ぶ with を使えばこの問題は消えます。
読むつもりで "w" を渡すと、ファイルの中身が空になってしまいます。"r" が読み、"w" が書きです。
read の結果をそのまま return すると、行のリストではなく 1 本の文字列が返ります。splitlines を通してからにします。
write に改行を期待するwrite("りんご") を 2 回呼んでも 2 行にはならず、りんごりんご と横につながります。改行は自分で書きます。
write にリストを渡すf.write(["a", "b"]) は TypeError になります。write が受け取れるのは文字列だけなので、先に join で 1 本にします。
f.write(120) も TypeError です。金額を書くときは str(120) で文字列にしてからにします。
with open(path, "w") as f の行末にはコロンが必要で、次の行はインデントします。忘れると SyntaxError になります。
f を使うブロックを抜けたあとに f.read() を呼ぶと ValueError になります。閉じたファイルは読めません。
with を使ったのに close も書く動きはしますが二重に閉じる意味のない行です。with を使ったら close は書きません。
str を付け忘れる",".join([name, price, category]) のように int を混ぜると TypeError になります。エラーメッセージは sequence item 1 と、何番目が悪いかを教えてくれます。
項目の区切りは ","、行の区切りは "\n" です。両方 join で書くので取り違えやすい部分です。
"りんご, みかんセット" のようにカンマを含む品名を保存すると、読み戻したときに項目数が合わなくなります。このコースでは品名にカンマを使わない前提にしますが、実務では標準ライブラリの csv を使ってこの問題を避けます。
except の範囲を広げすぎるexcept: とだけ書くと、あらゆる例外を飲み込んでしまいます。本当のバグまで隠れて原因が追えなくなるので、受け止める種類は必ず書きます。
try の範囲を広げすぎるtry のブロックに関係ない処理まで入れると、どこで失敗したのか分からなくなります。危ない 1 行だけを囲むのが基本です。
except で何もしないexcept ValueError: pass と書くと、失敗を無視して先に進みます。今回は 0 を返すという後始末があるので、pass は使いません。
except の種類を間違えるexcept ValueError では FileNotFoundError を受け止められません。関係のない種類を書くと、例外はそのまま素通りして止まります。
try に with を入れ忘れるwith の外側だけ try で囲んでも意味がありません。open が呼ばれる場所が try の中に入っている必要があります。
None の判定に == を使うinitial_text is not None と書きます。空文字も「渡された」として扱いたいので、if initial_text: では空文字が省略扱いになってしまいます。
int に戻し忘れる金額が "120" のまま返ると、見た目は似ていてもテストは落ちます。辞書に入れる前に int(price) を通します。
保存の形式は name、price、category の順です。読み戻すときも同じ順で受け取ります。キー名は第 7 章から一貫して英語です。
records を返すテストは通ってしまうかもしれませんが、保存できたことの確認になりません。必ずファイル経由で戻します。
つくる:保存機能で詳しく読むcommand[0] 以外を先に取り出してしまう["summary"] は要素が 1 つしかないので、いきなり command[1] を読むと IndexError になります。操作名で分岐したあと、その枝の中で取り出します。
同じ品名が 2 件あるとき、remove を繰り返すと両方消えます。1 件だけ消すなら break でループを抜けます。
add のたびに合計を作り直すと、delete のあとにずれます。最後にまとめて足すほうが確実です。
remaining を合計の途中で計算するループの中で引くと、最後の記録を足す前の値が残ります。引き算はループを抜けたあとです。
月間レポート機能で詳しく読むtop に金額を入れてしまうtop は品名の文字列です。top_price は探すための作業用の変数で、戻り値には入れません。
使いすぎたときの remaining は負の数のままにします。-500 と出るからこそ、いくら超えたのかが分かります。
in の向きを逆にするrecord["name"] in keyword と書くと、品名がキーワードに含まれるかという逆の判定になります。ほとんどの場合ずっと偽になります。
None を返す呼び出し側が for で回した瞬間に TypeError になります。空のリストを返します。
remove で絞り込もうとすると、元の記録が壊れます。新しいリストに集めるのが安全です。