質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

1782閲覧

自販機のプログラムコードを添削してほしい

yudouhu

総合スコア16

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2022/03/13 08:51

簡単な自販機のプログラミングを書いたのですが、周囲の添削してくれる人がいないので添削して頂きたいです。

主に添削してほしい箇所はコメントで記載しています。
しかし、全体としてコードが長く見ずらい部分が多々あるので、どこを関数化するなどのアドバイスも頂けますと幸いです。

前提条件として

・お札投入口はない
・投入は複数回
・投入金額の総計を取得できる
・払い戻しで、投入金額の総計をつり銭として出力

の4つがあります。

どなたか、ご指導ご鞭撻のほどよろしくお願いいたします。

python

1drink_lists = [["Cola",120,5],["Soda",100,4]] 2sum = int(0) 3sales_profit = int(0) 4 5while True: 6 select_button = input("chose button,1:投入,2:払い戻し,3:購入,4:在庫確認 \n") 7 8 if int(select_button) == 1: 9 10 print("使用できる通貨は,10円,50円,100円,500円の4種類です。 紙幣・1円と5円は使用することができません") 11 paid_in = input("金額を投入してください") 12 paid_in = int(paid_in) 13 14 #もっと簡略化できないか? 15 if paid_in == 10 or paid_in == 50 or paid_in == 100 or paid_in == 500: 16 sum = sum + paid_in 17 print("金額合計:",sum) 18 19 else: 20 print("指定外の硬貨が投入されました") 21 break 22 23 elif int(select_button) == 2: 24 print("払い戻しが選択されました \n 払い戻し金額:",sum) 25 sum = 0 26 break 27 28 elif int(select_button) == 3: 29 print("購入が選択されました \n 現在の投入金額:",sum) 30 31 i = int(0) 32 33 for drink_list in drink_lists: 34 print(i,":",drink_lists[i][0]) #print(drink_list[i][0])ではエラーが出る 35 i += 1 36 37 select_drink = input("購入する商品を選んでください \n") 38 39 #select_drink が数字の場合 40 if select_drink.isdigit(): 41 select_drink = int(select_drink) 42 #商品増加の都度、足していく必要がある? 43 if sum >= drink_lists[select_drink][1] and drink_lists[select_drink][2] >= 0: 44 print(drink_lists[select_drink][0] + "を購入しました\n") 45 #金額計算 46 sum = sum - drink_lists[select_drink][1] 47 #在庫減少 48 drink_lists[select_drink][2] -= 1 49 #売上計算 50 sales_profit = sales_profit + drink_lists[select_drink][1] 51 52 elif sum < drink_lists[select_drink][1]: 53 print("投入金額が足りません") 54 55 elif drink_lists[select_drink][2] == 0: 56 print("在庫がありません") 57 58 """ 59 存在しない商品を選ぶことはない前提で作る 60 else: 61 print("商品がありません") 62 break 63 64 """ 65 else: 66 print("商品を選択してください") 67 68 elif int(select_button) == 4: 69 print("売上は:",sales_profit,"円です") 70 i = 0 71 for drink_list in drink_lists: 72 #print(drink_list[i][0])ではエラーが出る 73 print("名前:",drink_lists[i][0],"値段",drink_lists[i][1],"在庫",drink_lists[i][2]) 74 i += 1 75 76 # 操作選択において、1,2,3,4以外(文字)が入力されたときの処理 77 else: 78 print("始めからやり直してください") 79

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2022/03/13 09:32

実際に動かして、きちんと動いてるんでしょうか
yudouhu

2022/03/13 09:50

大丈夫です。 動作確認はしており、きっちりと動いております。
guest

回答4

0

classの勉強はまだですかね?
添削ではなく、classを使った書き方を示しておきます。
役割毎にクラスを分けます。main関数: ユーザとのやりとり担当、VendingMachineクラス: 自動販売機
自動販売機の中に、商品を入れるレーン(Stocker:在庫管理担当)を置くのが楽かと思います。

python

1class Stocker: 2 3 def __init__(self, name, price, stock): 4 self._name = name 5 self._price = price 6 self._stock = stock 7 8 @property 9 def name(self): 10 return self._name 11 12 @property 13 def price(self): 14 return self._price 15 16 @property 17 def stock(self): 18 return self._stock 19 20 def eject(self): 21 if self.stock <= 0: 22 raise ValueError("在庫がありません") 23 self._stock -= 1 24 return self.name 25 26 27class VendingMachine: 28 29 def __init__(self, stockers): 30 self._stockers = dict(enumerate(stockers, 1)) 31 self._money = 0 32 self._sales = 0 33 34 @property 35 def money(self): 36 return self._money 37 38 @property 39 def sales(self): 40 return self._sales 41 42 def lineup(self): 43 for number, stocker in self._stockers.items(): 44 yield number, stocker.name, stocker.price 45 46 def status(self): 47 for stocker in self._stockers.values(): 48 yield stocker.name, stocker.price, stocker.stock 49 50 def insert(self, money): 51 if money not in (10, 50, 100, 500): 52 raise ValueError("指定外の金額が投入されました") 53 self._money += money 54 55 def cancel(self): 56 money = self._money 57 self._money = 0 58 return money 59 60 def buy(self, number): 61 if number not in self._stockers: 62 raise ValueError("商品を選択してください") 63 price = self._stockers[number].price 64 if self.money < price: 65 raise ValueError("投入金額が足りません") 66 self._money -= price 67 self._sales += price 68 return self._stockers[number].eject() 69 70 71vending_machine = VendingMachine([ 72 Stocker(name="Cola", price=120, stock=5), 73 Stocker(name="Soda", price=100, stock=4), 74]) 75 76 77def insert(): 78 print("使用できる硬貨は,10円,50円,100円,500円の4種類です。") 79 print("紙幣と1円と5円は使用することができません。") 80 money = input("硬貨を投入してください: ") 81 if not money.isdigit(): 82 print("硬貨ではありません") 83 return 84 try: 85 vending_machine.insert(int(money)) 86 print(f"投入合計: {vending_machine.money}円") 87 except ValueError as error: 88 print(str(error)) 89 90 91def cancel(): 92 print("払い戻しが選択されました") 93 money = vending_machine.cancel() 94 print(f"払い戻し金額: {money}円") 95 96 97def buy(): 98 print("購入が選択されました") 99 print("現在の投入金額:", vending_machine.money) 100 for number, name, price in vending_machine.lineup(): 101 print(f"{number}: {name} {price}円") 102 103 selection = input("購入する商品の番号を選んでください: ") 104 if not selection.isdigit(): 105 print("商品がありません") 106 return 107 108 try: 109 drink = vending_machine.buy(int(selection)) 110 print(f"{drink}を購入しました") 111 except ValueError as error: 112 print(str(error)) 113 114 115def status(): 116 print(f"売上は {vending_machine.sales}円です") 117 for name, price, stock in vending_machine.status(): 118 print(f"商品名:{name}、価格:{price}、在庫:{stock}") 119 120 121def main(): 122 actions = { 123 "1": insert, 124 "2": cancel, 125 "3": buy, 126 "4": status, 127 } 128 while True: 129 print() 130 selection = input("選択 1:投入、2:払い戻し、3:購入、4:在庫確認 ? ") 131 if selection in actions: 132 actions[selection]() 133 else: 134 print("始めからやり直してください") 135 136 137if __name__ == '__main__': 138 main()

投稿2022/03/13 18:29

編集2022/03/14 01:16
shiracamus

総合スコア5406

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yudouhu

2022/03/14 14:25

shiracamusさん、ありがとうございます。 クラスの勉強はまだというよりも、一度コードに落としてからでないと考えられないという具合です。 また、クラスを使った書き方は大変見やすいコードになっているので、参考にさせて頂きます。 重ね重ね、ありがとうございました。
guest

0

どういう観点で見てほしいのかよくわからないので、思ったことをいくつか書いてみます。

  • 特に長いとは思わないし、それなりにきれいに書けていると思います。

  • 関数化するのは、select_buttonの各処理の内容ごとがいいと思います。
    関数内で処理をして処理結果を返してループを制御する感じにします。

  • 異常な入力の時の処理に一貫性が無い
    購入時に数値以外を入れると、商品を選択しろと出るのに処理選択に戻ってしまうとか、想定外の金額を入れると終了してしまうとか。

  • プログラミング的なアドバイス

i を使って数えているところは enumerateを使うとすっきりします。

python

1 i = int(0) 2 3 for drink_list in drink_lists: 4 print(i,":",drink_lists[i][0]) #print(drink_list[i][0])ではエラーが出る 5 i += 1

python

1 for i, drink_list in enumarate(drink_lists): 2 print(i,":",drink_lists[i][0]) #print(drink_list[i][0])ではエラーが出る

#もっと簡略化できないか?

上のものは下のように書けます。

python

1 if paid_in == 10 or paid_in == 50 or paid_in == 100 or paid_in == 500: 2 3 if paid_in in [10, 50, 100, 500]: 4

print(drink_list[i][0])ではエラーが出る

drink_lists[i][0] でしょう。 s が抜けています。


こんなところです。

投稿2022/03/13 11:05

TakaiY

総合スコア12743

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

いろいろ仕様が変な気がしますが(値段不明の商品を購入する、在庫の無い商品まで表示する等)、そこはさておくと、
・無意味な空行がある
sum = int(0)などで、何故int関数を使っているのか意味不明
for文の理解が足りない
・入力を、文字列として扱うか数値に変換して扱うかの考慮が足りてない
・変数名が変(profitは「利益」ですが?等)
あたりが、気になるところです。

仕様はそのままで書き直すと、

Python

1drink_list = [["Cola",120,5],["Soda",100,4]] 2paid = 0 3sales = 0 4 5while True: 6 select_button = input("chose button,1:投入,2:払い戻し,3:購入,4:在庫確認 \n") 7 8 if select_button == "1": 9 print("使用できる通貨は,10円,50円,100円,500円の4種類です。 紙幣・1円と5円は使用することができません") 10 coin = input("金額を投入してください") 11 if coin in ["10","50","100","500"]: 12 paid += int(coin) 13 print("金額合計:",paid) 14 else: 15 print("指定外の硬貨が投入されました") 16 17 elif select_button == "2": 18 print("払い戻しが選択されました \n 払い戻し金額:",paid) 19 paid = 0 20 21 elif select_button == "3": 22 print("購入が選択されました \n 現在の投入金額:",paid) 23 for i, drink in enumerate(drink_list): 24 print(i,":",drink[0]) 25 26 select_drink = input("購入する商品を選んでください \n") 27 if select_drink.isdigit(): 28 drink = drink_list[int(select_drink)] 29 if paid < drink[1]: 30 print("投入金額が足りません") 31 elif drink[2] == 0: 32 print("在庫がありません") 33 else: 34 print(drink[0] + "を購入しました\n") 35 paid -= drink[1] 36 drink[2] -= 1 37 sales += drink[1] 38 """ 39 存在しない商品を選ぶことはない前提で作る 40 else: 41 print("商品がありません") 42 break 43 44 """ 45 else: 46 print("商品を選択してください") 47 48 elif select_button == "4": 49 print("売上は:",sales,"円です") 50 for drink in drink_list: 51 print("名前:",drink[0],"値段",drink[1],"在庫",drink[2]) 52 53 # 操作選択において、1,2,3,4以外(文字)が入力されたときの処理 54 else: 55 print("始めからやり直してください")

仕様そのままと書きましたが、
・数字じゃないものを入力するとエラー終了するのを改善
・在庫ゼロでも買えてしまうのを改善
・リストに無いコイン入力時や払い戻し時にプログラム終了するのも何だかなと思うので、breakを削除
だけ変えています。

投稿2022/03/13 10:41

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yudouhu

2022/03/13 11:34

otnさん、ご教示ありがとうございます。 for文とenumerate関数をもう少し勉強します。 TakaiYさんもご指摘ありがとうございました。 関数のアドバイスは参考にさせて頂きます。
otn

2022/03/13 12:31

全部自力で書いたのであれば、改善点はあった物の、在庫ゼロの場合以外はバグも無く、よく書けていると思います。 関数化するのであれば、一旦関数無しで書いてあとから関数にして外に出すというより、 設計の最初から、機能分割を考えて処理を書くのでしょうね。
yudouhu

2022/03/14 14:18

>関数化するのであれば、一旦関数無しで書いてあとから関数にして外に出すというより、 設計の最初から、機能分割を考えて処理を書くのでしょうね。 otnさん、アドバイスありがとうございます。 まだまだその域には達していませんが、コードを書く際の参考にさせて頂きます。
guest

0

レビュー以前の問題が2つ。

  1. lint チェックする
  2. テストを書く

lint 実行例

イメージ説明

イメージ説明

投稿2022/03/18 14:47

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問