1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

roboterを簡易的に記述しました。【現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用】

Last updated at Posted at 2022-08-14

概要

 Udemyの酒井潤さん(以下酒井先生と呼ばせていただきます)の講座「現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル」(以下Python3入門+応用)にてプログラミングを勉強しています。

講座のページはこちら

 酒井先生はシリコンバレーで現役のプログラマーとして活躍されているお方で、超一流のプログラミング技術を学ぶことができる大変貴重な講座です。

 こちらの講座ではセクション9にて仕様書にしたがったプログラミングの課題があるのですが、実際にクライアントの依頼に沿って成果物を納品するという想定になっています。酒井先生の模範解答はMVCモデルというソフトウェアの設計モデルを用いて書かれていますから、このように現場で使われている記述方法が学べるという点においても他の追随を許さない大変実りのあるものとなっています。

 しかしながら、現場経験がなく基礎的な本から学んだだけの私にとって、模範解答はあまりにも洗練されすぎていて、初見では到底記述することができないものでした。コースのQ&Aでもこのあたりから突然レベルが上がったと感じている方が多くいたことが見て取れ、おそらく私と同じように現場経験がないような方々が躓かれているという印象を受けました。

 そこで今回は、プログラミング初心者がこの課題に取り組んだらそのようなコーディングになるのかを記述することで、同じくこちらの課題に悩まれている方にとって理解の一助となることを目的としています。

 なお
・こちらに記述されているコーディング技術は、すべて講座内の講義にて習得することが可能であること
・私も実際にプログラムを組み、1つの関数を除いて自分の力だけで書くことができたこと

を付け加えさせていただきます。あとは繰り返しになりますが、私のコードは、酒井先生が書かれている実践を想定した模範解答からは大きくはずれていますのでご注意を…。

プログラム

実行系統の「main.py」と関数を詰め込んだ「robotter.py」の2つに分かれています。

main.py

#自作のrobotterをインポート
import robotter

#変数の宣言
csv_path ="ranking.csv"

#お客さんの名前を入力してもらう
name = input("こんにちは!私の名前はRobokoです。あなたの名前は何ですか?")

#robotterインスタンスを生成。名前は後で使うから渡してself.nameに入れておく
robotter = robotter.RestaurantRobot(name)

#csv_pathを渡して、もしファイルがなければ作成し、あれば読み込みを行う
robotter.load_csv(csv_path)

#ロボットからレストランをおすすめ順にサジェストする
robotter.recommend_restaurant()

#ユーザーのおすすめを聞く
user_recommend_restaurant_name = robotter.ask_user_favorite()

#ファイルへ書き込む
robotter.write_csv(user_recommend_restaurant_name)
robotter.py
#ライブラリのインポート
import collections
import csv
import os
import pathlib

#RestaurantRobotクラスの宣言
class RestaurantRobot(object):
    def __init__(self, name):
        self.name = name

    #csvファイルを読み込むメソッド
    def load_csv(self,csv_path):
        #もしcsvファイルがなければ空のファイルを作成する
        if not os.path.isfile(csv_path):
            pathlib.Path(csv_path).touch()

        #辞書(defaultdict)型の変数dataを用意
        self.data = collections.defaultdict(int)

        #csvの中身を辞書として読み込んで変数dataに入れる(辞書型)
        with open(csv_path,"r") as f:
            reader = csv.DictReader(f)
            for row in reader:
                self.data[row["NAME"]] = int(
                    row["COUNT"]
                ) #最初はdataには何も入らない。


    #レストランをおすすめ順にサジェストするメソッド
    def recommend_restaurant(self):

        # 最も人気のレストラン名を1つ返すメソッド(関数内関数)
        def get_most_popular_restaurant(not_list=None):
            if not_list is None:
                not_list = []
            if not self.data:
                return None

            restraunt_names = sorted(self.data, key=self.data.get, reverse=True)
            for restraunt_name in restraunt_names:
                if restraunt_name in not_list:
                    continue
                return restraunt_name

        # 最も票数の多いレストランの名前を取得する
        restaurant_name = get_most_popular_restaurant()

        #もしデータがなければNoneを返す
        if not restaurant_name:
            return None

        #今取得したレストラン名をリストに格納する。最終的にnot_listへ渡す
        ex_restaurant_list = [restaurant_name]

        #yesまたはリストの終わりまでレストランをサジェストし続ける。
        while True:
            yes_no = input(f"私のおすすめは{restaurant_name}です。"
                           f"あなたはこのレストランが好きですか?[Yes/No]")

            if yes_no.lower() == "y"or yes_no.lower()=="yes":
                break
            if yes_no.lower() == "n" or yes_no.lower() == "no":
                restaurant_name = get_most_popular_restaurant(
                    not_list = ex_restaurant_list)

                #もしもうレストランの名前が返ってこなかったらwhileを抜ける
                if not restaurant_name:
                    break

                #取得したレストラン名はappendしてためておく
                ex_restaurant_list.append(restaurant_name)

    #ユーザーのおすすめレストランを聞くメソッド
    def ask_user_favorite(self):
        user_recommended_restaurant_name = input(f"{self.name}さんのおすすめのレストランを教えてください").title()
        return user_recommended_restaurant_name

    #ファイルへ書き込むメソッド
    def write_csv(self,restaurant_name):
        #キーにレストランの名前があれば値に+1、なければキーを作って値に1を入れる
        self.data[restaurant_name.title()] += 1
        with open("ranking.csv", "w", newline="") as f:
            fieldnames = ["NAME", "COUNT"]
            writer = csv.DictWriter(f, fieldnames=fieldnames)
            writer.writeheader()
            for name,count in self.data.items():
                writer.writerow({"NAME":name,"COUNT":count})

雑感

 最も人気のレストランを返すget_most_popular_restaurantメソッドの作成が難関でした。私は最初辞書型のdataをそのままソートしようと試みました。実際に方法はあるようですが、学習していない内容だったので別の方法を考えたのですが、値の降順でキーを並べ替えてキーだけをリストにいれればよかったんですね…。この関数だけは自作することができず、模範解答を参考にさせていただきました。

最後に

 コードを見ていただいて、おかしな点やがあったり「私はこう書いたよ!」というコードがあればぜひ共有いただきたいと思います。
 また私は趣味でプログラミングを勉強している日曜プログラマーですが、酒井先生の講座は「Python3入門+応用」以外にもいくつか講座を履修しました。そのおかげで、知人が行っていた企業向けのプログラミング研修の教本の編纂に携わることができました。私では到底入ることができないような、一流企業の新入社員さん向けの研修に使われているそうです。
私も入社したい…。この場を借りてお礼申し上げます。

※こちらの記事は講座内容を含むため、許可を取っています。

追記

こちらのプログラムは酒井先生の「シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全」にも掲載されているようです。
アフィリエイトついてません

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?