Python学習【365日チャレンジ!】108日目のマスターU(@Udemy11)です。
ホットケーキミックスが品薄になっていたらしですが、大量の買いだめには注意が必要なようです。
というのも、小麦粉の中には、ダニの卵が含まれているので、長期間保存することでダニが大量に発生して、ダニアレルギーでアナフラキシーショックを起こしてしまうことがあるらしいからです。
2004年の記事なので、少し古いですが、この報告によると、小麦粉によるアナフラキシーショックが報告されていて、その後の調査で、日本の小売店の176パッケージの中から3個、家庭の127パッケージの中から7個にダニの蔓延が見つかったそうです。
ただ、冷蔵庫に保存されていたパッケージからはダニは検出されなかったそうなので、小麦粉は冷蔵庫に保存したほうがいいようですね。
そういえば、以前米不足になったときに米屋さんから聞いた話では、日本の米は1年もほっておけば、中で虫が成長してカサカサ音がなってくるけど、輸入したタイ米は、何年立っても虫がわかないなんてことを言ってました。
タイ米には、それだけ強力な殺虫剤が使われているということですね。
毎日口にするものなので、このあたりのことには注意したいものです。
ということで、今日もPython学習にはいりましょう!
昨日の復習
昨日は、オブジェクト指向作成したJarvis
クラスで2人目の質問に対応させました。
1人目と2人目の違いは、条件分岐があるかどうかだったので、1人目に比べるとコードが長くなりましたが、何も考えずに作った最初のコードに比べるとかなりわかりやすくなったかと思います。
1人目と大きくちがったのは、__init__(self)
による初期化とCSVの書き込みのための関数を加えたところでした。
内容については、昨日の記事をごらんください。
それでは、クラスを使ったコードを完成させましょう!
追加するコード
1人目、2人目をカバーする質問と3人め以降の質問で大きく違うのは、CSVに保存しているデータを並び替えておすすめするスポーツを抽出することと、大好きなスポーツがすでにあるデータかどうかを判断して、CSVに追加するところです。
まず、CSVのデータを取り出して順番に並べ替えるためにoperator
モジュールをインポートしてデータを並び替える必要があります。
次に、おすすめするスポーツが好きかどうかの判断によって条件分岐を加えます。
最後は、CSVファイルへの書き込みも条件によって変える必要があります。
これらの追加コードについて、前回のコードから変更された部分について紹介していきます。
__init__(self)の変更
まず、インポートするモジュールを追加し、そのモジュールを使って、データを並び替え、おすすめするスポーツを取り出せるジェネレーターを作ります。
import csv
import operator
import os
class Jarvis(object):
def __init__(self):
sel.check = ps.path.exixts('ranking.csv')
self.fieldnames = ('NAME', 'COUNT')
if self.check is True:
with open('ranking.csv', 'r') as rank_csv:
ranking = csv.DictReader(rank_csv)
result = sorted(ranking, key=operator.itemgetter('COUNT'), reverse=True)
self.recommend = (i['NAME'] for i in result)
あとでCSVファイルに書き込むためのself.fieldnames
も初期化の際に定義しておきます。
ranking.csv
が存在するときに、ファイルを開いて、おすすめするスポーツをCOUNT
の数が多い順に並べ替えています。
y_or_n(self)の変更
次に、おすすめするスポーツが好きかどうかの条件分岐は、昨日は、ここで条件を判断しませんでしたが、3人目以降は回答によって次の質問が変わってくるので、条件分岐を入れる必要があります。
def y_or_n(self):
r_sport = next(self.recommend)
while True:
try:
y_n = input('\nわたしのおすすめのスポーツは{}です。\nあなたはこのスポーツが好きですか? [Yes/No]\n'.format(r_sport))
if 'Y' in str.upper(y_n):
break
elif 'N' in str.upper(y_n):
r_sport = next(self.recommend)
continue
else:
print('\nYes か No で答えてください。')
except:
break
回答がYes
かY
の場合は、break
でこのループを抜けます。
No
もしくはN
の場合は、初期化で取得したジェネレーターから次の値をr_sport
に代入して、ループを繰り返します。
回答に、Y
もN
も含まれていない場合は、Yes
かNo
で答えるように質問し、ループを繰り返します。
try except
でジェネレーターの値がなくなったときのエラーを返さずにループを抜けるようにしています。
write_csv(self)の変更
def write_csv(self):
if self.check is True:
with open('ranking.csv', 'r') as rank_c:
ranking = csv.DictReader(rank_c)
refresh_csv = []
for i in ranking:
if i['NAME'] == self.c_like_sports:
num = i['COUNT']
a_num = int(num) + 1
i['COUNT'] = a_num
refresh_csv.append(i)
rank_c.seek(0)
check_sports = []
for j in ranking:
check_sports.append(j['NAME'])
if self.c_like_sports in check_sports:
with open('ranking.csv', 'w') as rank_csv:
writer = csv.DictWriter(rank_csv, fieldnames=self.fieldnames)
writer.writeheader()
writer.writerows(refresh_csv)
else:
with open('ranking.csv', 'a') as rank_csv:
writer = csv.DictWriter(rank_csv, fieldnames=self.fieldnames)
writer.writerow({'NAME': self.c_like_sports, 'COUNT': 1})
else:
with open('ranking.csv', 'w', encoding='UTF-8') as rank_csv:
writer = csv.DictWriter(rank_csv, fieldnames=self.fieldnames)
writer.writeheader()
writer.writerow({'NAME': self.c_like_sports. 'COUNT':1})
大きな条件分岐であるranking.csv
の有無については昨日と同じで、ない場合は、ranking.csv
を作成して、取得したデータを書き込みます。
ranking.csv
がある場合は、データを取得して、回答されたデータがすでにある場合は、そのCOUNT
の値に1
を足して、それ以外の場合は、そのまま変数redresh_csv
に代入していきます。
次に、取得したデータの読み込み位置をrank_c.seek(0)
でもとに戻してから変数check_sports
にスポーツ名を代入します。
最後に、check_sports
の中に、ユーザーが入力したスポーツc_like_spotrs
が含まれていれば、ranking.csv
に、変数refresh_csv
の値を上書きし、含まれていなければ、スポーツ名c_like_sports
をranking.csv
に追記します。
完成したコード
上記の部分を昨日のコードに追加すれば、3人目以降の質問に対応できるコードの完成です。
import csv
import operator
import os
class Jarvis(object):
def __init__(self):
self.check = os.path.exists('ranking.csv')
self.fieldnames = ('NAME', 'COUNT')
if self.check is True:
with open('ranking.csv', 'r') as rank_csv:
ranking = csv.DictReader(rank_csv)
result = sorted(ranking, key=operator.itemgetter('COUNT'), reverse=True)
self.recommend = (i['NAME'] for i in result)
def say_hello(self):
name = input('こんにちは。わたしはジャービスです。あなたの名前を教えてください。\n')
self.c_name = name.title()
return self.c_name
def y_or_n(self):
r_sport = next(self.recommend)
while True:
try:
y_n = input('\nわたしのおすすめのスポーツは{}です。\nあなたはこのスポーツが好きですか? [Yes/No]\n'.format(r_sport))
if 'Y' in str.upper(y_n):
break
elif 'N' in str.upper(y_n):
r_sport = next(self.recommend)
continue
else:
print('\nYes か No で答えてください。')
except:
break
def ask_main(self):
like_sports = input('\n{}さん、あなたの好きなスポーツは何ですか?\n英語で答えてください\n'.format(self.c_name))
self.c_like_sports = like_sports.title()
return self.c_like_sports
def write_csv(self):
if self.check is True:
with open('ranking.csv', 'r') as rank_c:
ranking = csv.DictReader(rank_c)
refresh_csv = []
for i in ranking:
if i['NAME'] == self.c_like_sports:
num = i['COUNT']
a_num = int(num) + 1
i['COUNT'] = a_num
refresh_csv.append(i)
rank_c.seek(0)
check_sports = []
for j in ranking:
check_sports.append(j['NAME'])
if self.c_like_sports in check_sports:
with open('ranking.csv', 'w') as rank_csv:
writer = csv.DictWriter(rank_csv, fieldnames=self.fieldnames)
writer.writeheader()
writer.writerows(refresh_csv)
else:
with open('ranking.csv', 'a') as rank_csv:
writer = csv.DictWriter(rank_csv, fieldnames=self.fieldnames)
writer.writerow({'NAME': self.c_like_sports, 'COUNT': 1})
else:
with open('ranking.csv', 'w', encoding='UTF-8') as rank_csv:
writer = csv.DictWriter(rank_csv, fieldnames=self.fieldnames)
writer.writeheader()
writer.writerow({'NAME': self.c_like_sports, 'COUNT': 1})
def __del__(self):
print('\n{}さん、回答ありとうございました。\n良い1日をお過ごし下さい!'.format(self.c_name))
if __name__ == '__main__':
jarvis = Jarvis()
jarvis.say_hello()
if jarvis.check is True:
jarvis.y_or_n()
jarvis.ask_main()
jarvis.write_csv()
del jarvis
最後には、実行コードの場合に実行するためのif __name__ = '__main__':
に続けて、オブジェクトJarvis
を作成し、関数を実行します。
今あるスキルで
今日までの6日ほどの内容は、これまで学習してきた入門編の内容を考えながら、自分なりにコードを考えて書いたので、理想的なコードとはほどとおい内容になってしまっているので、参考にはならないかもしれません。
とはいえ、自分で考えずに、先に模範解答を見てからコードを考えるのと、自分でなんとか課題をクリアするコードを考えるのでは、大きな違いが出てくると思います。
教えられたものをそのままやるのと、自分なりに工夫してやるのでは、身につくスキルも違ってきます。
答えを知った上で復習するか、やってみてから答えを知るのとの違いですよね。
明日からは、アプリケーションを開発する上での基本的な構造の考え方を踏まえた上で、模範となるコードを学習していきます。
それでは、明日もGood Python!