つくる:カテゴリ自動判定

このレッスンで作るもの — 第 4 章の総仕上げとして、品名からカテゴリを言い当てる guess_category を作ります。おこづかい帳が入力を肩代わりしてくれるようになります。

つくる — カテゴリ自動判定

第 3 章までのおこづかい帳は、言われたことをそのまま整形するだけの道具でした。第 4 章で条件分岐を手に入れたので、ここで一歩進めます。品名を渡すだけでカテゴリを推測する 関数 guess_category です。

これがあると、記録するたびに「これは食費、これは娯楽」と人間が選ぶ手間がなくなります。

判定に使うキーワード

品名の中に決まった言葉が含まれているかで判定します。使うキーワードは下記のとおりです。

  • 食費りんご / パン / 牛乳
  • 日用品ティッシュ / 洗剤 / 歯ブラシ
  • 娯楽映画 / ゲーム / マンガ
  • 交通費電車 / バス / タクシー
  • その他 — 上のどれも含まれないとき

カテゴリはこの 5 種類だけです。おこづかい帳全体で使うカテゴリ名と一字一句そろえます。

判定の材料は、コードを書き始める前に文章で書き出しておきます。ここが曖昧なまま if を書き始めると、どこまで書けば完成なのか自分でも分からなくなります。

文字列に含まれるかを調べる

第 3 章の in 演算子は、文字列に対しても使えます。左に部分文字列、右に調べたい文字列を書くと、含まれていれば True になります。

"りんご" in "りんご3個" # True "りんご" in "みかん" # False

つまり "りんご" in name と書けば、品名が りんご そのものでも りんご3個 でも True になります。完全一致の == より当てはまる範囲が広く、実際の入力に強くなります。

組み立てる

キーワードの候補は or でつなぎ、カテゴリごとに elif で分けます。

def guess_category(name): if "りんご" in name or "パン" in name or "牛乳" in name: return "食費" elif "ティッシュ" in name or "洗剤" in name or "歯ブラシ" in name: return "日用品" elif "映画" in name or "ゲーム" in name or "マンガ" in name: return "娯楽" elif "電車" in name or "バス" in name or "タクシー" in name: return "交通費" return "その他"

最後の return "その他"elif の外側に置きます。どのカテゴリにも当てはまらなかったときに、ここへ落ちてきます。

diagram (will load when visible)

動きを追ってみる

guess_category("映画のチケット") の流れは下記のとおりです。

  1. 食費の 3 つのキーワードはどれも含まれず False
  2. 日用品の 3 つも False
  3. 娯楽の "映画" in nameTrue になり、return "娯楽" で終わる

guess_category("ノート") なら 4 つの elif をすべてすり抜けて return "その他" に到達します。「当てはまらない道」を必ず用意しておくのが、この形の肝です。

どの分岐にも入らなかったときの行き先を先に決めておくと、None が返る事故が起きません。分岐を書いたら最後の受け皿を確認する癖を付けます。

この仕組みの限界

部分一致には弱点があります。バスタオル は日用品ですが バス を含むので交通費と判定されます。キーワードの当て方を工夫するか、品名とカテゴリの対応表を持つかで改善できますが、対応表を扱うには第 7 章の辞書が必要です。

今の道具で作れる範囲の、いちばん実用的な形がこれです。限界を知ったうえで使うのと、知らずに使うのとでは大違いです。

よくある間違い

  1. name in "りんご" と左右を逆に書くin は左が探すもの、右が探される場所です。逆にすると意味が反転します。
  2. or のたびに in を書き忘れるif "りんご" or "パン" in name:"りんご" が常に True 扱いになるため、すべて食費になります。or でつなぐのは条件そのものです。
  3. 最後の受け皿を忘れるelif だけで終えると、どれにも当てはまらない品名で None が返ります。

やってみよう

関数 guess_category(name) を実装してください。上のキーワード表のとおりに判定し、食費 / 日用品 / 娯楽 / 交通費 / その他 のいずれかを返します。

キーワードは in で部分一致を見ます。書けたら りんご 洗剤 映画のチケット 電車代 ノート の 5 つを渡して、5 種類の答えがすべて出ることを確かめてみてください。

要件

  1. 関数名は guess_category で、引数は name の 1 つ
  2. name に りんご / パン / 牛乳 のいずれかが含まれるなら "食費" を return する
  3. name に ティッシュ / 洗剤 / 歯ブラシ のいずれかが含まれるなら "日用品" を return する
  4. name に 映画 / ゲーム / マンガ のいずれかが含まれるなら "娯楽" を return する
  5. name に 電車 / バス / タクシー のいずれかが含まれるなら "交通費" を return する
  6. 上のどれにも当てはまらないときは "その他" を return する
  7. 判定は == の完全一致ではなく in の部分一致で行う

入出力例

guess_category("りんご")"食費" guess_category("牛乳パック")"食費" guess_category("洗剤")"日用品" guess_category("歯ブラシ")"日用品" guess_category("映画のチケット")"娯楽" guess_category("電車代")"交通費" guess_category("タクシー代")"交通費" guess_category("ノート")"その他" guess_category("")"その他"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.py
main.py
学習モード

メモ

つくる:カテゴリ自動判定

⌘S で保存