『退屈なことはPythonにやらせよう』8章 入力検証のらくがき帳📝
こんにちは。aliceです。
昨日は久しぶりに梨を食べました。甘くてみずみずしくておいしかったです。食べ物から季節を感じています。
今回は『退屈なことはPythonにやらせよう』第8章 入力検証のらくがき帳です。
入力検証とは、input関数などでユーザーが入力した値が正しいかどうか調べることです。
あまりinput関数を使うようなコードを書いたことがないのですが、やってみたら普通に楽しかったです。
前回のらくがき帳📝
では、以下らくがきです。
8章 英語版🔤
GitHub💖
8.1 PyInputPlusモジュール
PyInputPlusモジュール、はじめて知った。
import pyinputplus as pyip
response = pyip.inputNum('数字を入力してください')
print(response)
inputNum関数の引数
いろいろある。
def inputNum(
prompt="", # プロンプト (入力を促す文字列)
default=None, # デフォルト値。デフォルト値が指定されている場合、ユーザーが何も入力せずに Enter キーを押した場合にデフォルト値が返されます。
blank=False, # 空白の入力を許可するかどうか
timeout=None, # タイムアウト時間 (秒)
limit=None, # 入力を受け付ける文字数の上限
strip=None, # 入力の前後にある空白を削除するかどうか
allowRegexes=None, # 正規表現のリスト。これらの正規表現に一致する入力は許可されます。
blockRegexes=None, # 正規表現のリスト。これらの正規表現に一致する入力は許可されません。
applyFunc=None, # 入力された値に対して呼び出される関数
postValidateApplyFunc=None, # 入力された値に対して呼び出される関数
min=None, # 最小値
max=None, # 最大値
greaterThan=None, # 最小値より大きい
lessThan=None, # 最大値より小さい
):
引数の位置と何があるかがわからないので、ちょこちょこ調べるスタイル。
8.1.5 inputCustom()に自作の検証関数を渡す
自分で作った関数でも入力検証できるらしい。
へぇぇ。
import pyinputplus as pyip
def adds_up_to_ten(numbers):
numbersList = list(numbers)
for i, digit in enumerate(numbersList):
numbersList[i] = int(digit)
if sum(numbersList) != 10:
raise Exception(f'足しても10になりません, {sum(numbersList)}です')
return int(numbers) # Return an int form of numbers.
response = pyip.inputCustom(adds_up_to_ten, prompt='合計が10になる数字を入力してください: ')
print(response)
8.3 プロジェクト:掛け算クイズ
せっかくなので2桁の足し算クイズにしてみた。
何気に難しい🥲
頭の運動にはぴったりでした。
こういうところでも正規表現を使えるんですね。
import random
import time
import pyinputplus as pyip
number_of_questions = 5
correct_answers = 0
for question_number in range(number_of_questions):
num1 = random.randint(11, 99)
num2 = random.randint(11, 99)
prompt = f'#{question_number}: {num1} + {num2} = '
try:
# 正解は allowRegexes で処理する
# 不正解は blockRegexes で処理され、カスタムメッセージが表示される
pyip.inputStr(
prompt,
allowRegexes=[f'^{num1 + num2}$'],
blockRegexes=[('.*', '残念!')],
timeout=10,
limit=3
)
except pyip.TimeoutException:
print('時間切れです!')
except pyip.RetryLimitException:
print('所定の回数を超えました!')
else:
# try ブロックで例外が発生しなかった場合に実行
print('正解!')
correct_answers += 1
time.sleep(1)
こういうのをサクッと考えられたらすごいなと思う。
正規表現を使わないとながーくなるんですね。
(ちょっとルールが変わった気がする💦)
import random
import time
import pyinputplus as pyip
def is_correct_answer(prompt, answer, tries=3, timeout=10):
for _ in range(tries):
try:
user_input = pyip.inputStr(prompt, timeout=timeout)
if user_input == answer:
print('正解!')
return True
else:
print('残念!')
except pyip.TimeoutException:
print('時間切れです!')
except pyip.RetryLimitException:
print('所定の回数を超えました!')
return False
number_of_questions = 5
correct_answers = 0
for question_number in range(number_of_questions):
num1 = random.randint(11, 99)
num2 = random.randint(11, 99)
answer = str(num1 + num2)
prompt = f'#{question_number}: {num1} + {num2} = '
if is_correct_answer(prompt, answer):
correct_answers += 1
time.sleep(1)
print(f'Score: {correct_answers} / {number_of_questions}')
8.6 演習プロジェクト
8.6.1 サンドイッチメーカー
ユーザーにサンドイッチの好みを尋ねるプログラムを書きましょう。
PyInputPlusモジュールを使うとさくっと書けるんですね🥪
import pyinputplus as pyip
def sandwich_maker():
bread = pyip.inputMenu(['小麦', '白パン', '全粒粉', 'ライ麦'], prompt='パンを選んでください:\n', )
protein = pyip.inputMenu(['チキン', 'ターキー', 'ハム', '豆腐'], prompt='タンパク質の種類を選んでください:\n', )
cheese = pyip.inputYesNo(prompt='チーズを追加しますか?\n', yesVal='はい', noVal='いいえ',)
if cheese == 'はい':
cheese = pyip.inputMenu(['チェダー', 'スイス', 'モッツァレラ'], prompt='チーズを選んでください:\n', )
else:
cheese = 'なし'
tomato = pyip.inputYesNo(prompt='トマトを追加しますか?\n', yesVal='はい', noVal='いいえ', )
lettuce = pyip.inputYesNo(prompt='レタスを追加しますか?\n', yesVal='はい', noVal='いいえ', )
mayo = pyip.inputYesNo(prompt='マヨネーズを追加しますか?\n', yesVal='はい', noVal='いいえ', )
mustard = pyip.inputYesNo(prompt='マスタードを追加しますか?\n', yesVal='はい', noVal='いいえ', )
count = pyip.inputInt(prompt='サンドイッチの数を入力してください:\n', min=1)
print(f'注文内容は以下の通りです:\n'
f'パン: {bread}\n'
f'タンパク質: {protein}\n'
f'チーズ: {cheese}\n'
f'トマト: {tomato}\n'
f'レタス: {lettuce}\n'
f'マヨネーズ: {mayo}\n'
f'マスタード: {mustard}\n'
f'サンドイッチの数: {count}\n'
f'ありがとうございました!')
if __name__ == '__main__':
sandwich_maker()
8.6.2 自作の掛け算クイズ
PyInputPlusモジュールのありがたみを実感するために、PyInputPlusモジュールを使わないで掛け算クイズを書きましょう。
ありがたみをとても実感できたのでChatGPTに書いてもらいました。
import random
import time
number_of_questions = 10
correct_answers = 0
for question_number in range(number_of_questions):
num1 = random.randint(0, 9)
num2 = random.randint(0, 9)
answer = num1 * num2
prompt = f'#{question_number}: {num1} x {num2} = '
attempts = 0
while attempts < 3:
user_input = input(prompt)
try:
user_answer = int(user_input)
except ValueError:
print('Invalid input. Please enter a number.')
continue
if user_answer == answer:
print('Correct!')
correct_answers += 1
time.sleep(1) # Brief pause to let user see the result.
break
else:
print('Incorrect!')
attempts += 1
if attempts == 3:
print('Out of tries!')
time.sleep(1) # Brief pause before moving to the next question.
print(f'Score: {correct_answers} / {number_of_questions}')
input関数で入力してもらうのも、なかなか楽しいです。
この記事が気に入ったらサポートをしてみませんか?