[解決済み] ユーザーが有効な応答を返すまで入力を求める
質問
ユーザーからの入力を受け付けるプログラムを書いています。
#note: Python 2.7 users should use `raw_input`, the equivalent of 3.X's `input`
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
ユーザが意味のあるデータを入力する限り、プログラムは期待通りに動作します。
C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!
しかし、ユーザーが無効なデータを入力した場合は失敗します。
C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Traceback (most recent call last):
File "canyouvote.py", line 1, in <module>
age = int(input("Please enter your age: "))
ValueError: invalid literal for int() with base 10: 'dickety six'
クラッシュするのではなく、再度入力を求めるようにしてほしい。このように。
C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Sorry, I didn't understand that.
Please enter your age: 26
You are able to vote in the United States!
無意味なデータが入力されたときに、プログラムがクラッシュするのではなく、有効な入力を求めるようにするにはどうしたらよいでしょうか?
のような値を拒否するにはどうすればよいですか?
-1
であり、有効な
int
しかし、この文脈では無意味ではないか?
どのように解決するのですか?
これを実現する最も簡単な方法は
input
メソッドをwhileループに入れる。使用方法
continue
は、悪い入力があったときに、そして
break
を、満足したらループから抜ける。
入力で例外が発生する可能性がある場合
使用方法
try
と
except
を使用して、ユーザーが解析できないデータを入力したことを検出します。
while True:
try:
# Note: Python 2.x users should use raw_input, the equivalent of 3.x's input
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
#better try again... Return to the start of the loop
continue
else:
#age was successfully parsed!
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
独自のバリデーションルールを実装する
Pythonが正常にパースできる値を拒否したい場合、独自の検証ロジックを追加することができます。
while True:
data = input("Please enter a loud message (must be all caps): ")
if not data.isupper():
print("Sorry, your response was not loud enough.")
continue
else:
#we're happy with the value given.
#we're ready to exit the loop.
break
while True:
data = input("Pick an answer from A to D:")
if data.lower() not in ('a', 'b', 'c', 'd'):
print("Not an appropriate choice.")
else:
break
例外処理とカスタムバリデーションの組み合わせ
上記の2つのテクニックは、1つのループにまとめることができます。
while True:
try:
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if age < 0:
print("Sorry, your response must not be negative.")
continue
else:
#age was successfully parsed, and we're happy with its value.
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
すべてを関数でカプセル化する
もしユーザーにたくさんの異なる値を尋ねる必要があるなら、このコードを関数の中に入れておくと、毎回入力し直す必要がなく便利です。
def get_non_negative_int(prompt):
while True:
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if value < 0:
print("Sorry, your response must not be negative.")
continue
else:
break
return value
age = get_non_negative_int("Please enter your age: ")
kids = get_non_negative_int("Please enter the number of children you have: ")
salary = get_non_negative_int("Please enter your yearly earnings, in dollars: ")
すべてをまとめる
このアイデアを拡張して、非常に汎用的な入力関数を作ることができます。
def sanitised_input(prompt, type_=None, min_=None, max_=None, range_=None):
if min_ is not None and max_ is not None and max_ < min_:
raise ValueError("min_ must be less than or equal to max_.")
while True:
ui = input(prompt)
if type_ is not None:
try:
ui = type_(ui)
except ValueError:
print("Input type must be {0}.".format(type_.__name__))
continue
if max_ is not None and ui > max_:
print("Input must be less than or equal to {0}.".format(max_))
elif min_ is not None and ui < min_:
print("Input must be greater than or equal to {0}.".format(min_))
elif range_ is not None and ui not in range_:
if isinstance(range_, range):
template = "Input must be between {0.start} and {0.stop}."
print(template.format(range_))
else:
template = "Input must be {0}."
if len(range_) == 1:
print(template.format(*range_))
else:
expected = " or ".join((
", ".join(str(x) for x in range_[:-1]),
str(range_[-1])
))
print(template.format(expected))
else:
return ui
などの用法で。
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
よくある落とし穴と、それを避けるべき理由
冗長な使い方
input
ステートメント
この方法は有効ですが、一般にスタイルが悪いとされています。
data = input("Please enter a loud message (must be all caps): ")
while not data.isupper():
print("Sorry, your response was not loud enough.")
data = input("Please enter a loud message (must be all caps): ")
よりも短いので、最初は魅力的に見えるかもしれません。
while True
メソッドに違反しますが、これは
同じことを繰り返さない
ソフトウェア開発の原則です。そのため、システムにバグが発生する可能性が高くなります。を変更して2.7にバックポートしたい場合はどうでしょうか?
input
から
raw_input
が、誤って最初の
input
上記の?それは
SyntaxError
を待つだけです。
再帰はあなたのスタックを吹き飛ばす
再帰について学んだばかりの人は、再帰を利用するために
get_non_negative_int
で、whileループを破棄することができます。
def get_non_negative_int(prompt):
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
return get_non_negative_int(prompt)
if value < 0:
print("Sorry, your response must not be negative.")
return get_non_negative_int(prompt)
else:
return value
ほとんどの場合、これは問題なく動作しているように見えますが、ユーザーが無効なデータを何度も入力すると、スクリプトが終了して
RuntimeError: maximum recursion depth exceeded
. しかし、あなたは愚か者の工夫を過小評価しているのです!あなたは、quot;どんな愚か者も1000回も連続して間違いを犯すことはないと思うかもしれません。
関連
-
ピローによる動的キャプチャ認識のためのPythonサンプルコード
-
Evidentlyを用いたPythonデータマイニングによる機械学習モデルダッシュボードの作成
-
風力制御におけるKS原理を深く理解するためのpythonアルゴリズム
-
Python LeNetネットワークの説明とpytorchでの実装
-
FacebookオープンソースワンストップサービスpythonのタイミングツールKats詳細
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み】socket.error: [Errno 48] アドレスはすでに使用中です。
-
[解決済み] 'DataFrame' オブジェクトに 'sort' 属性がない
-
[解決済み】Python: SyntaxError: キーワードは式になり得ない
-
[解決済み】ValueError: pickleプロトコルがサポートされていません。3、python2 pickleはpython3 pickleでダンプしたファイルを読み込むことができない?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
opencvとpillowを用いた顔認証システム(デモあり)
-
パッケージングツールPyinstallerの使用と落とし穴の回避
-
Python入門 openを使ったファイルの読み書きの方法
-
PythonによるExcelファイルの一括操作の説明
-
Pythonの画像ファイル処理用ライブラリ「Pillow」(グラフィックの詳細)
-
PythonでECDSAを実装する方法 知っていますか?
-
[解決済み] _tkinter.TclError: 表示名がなく、$DISPLAY環境変数もない。
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み】csv.Error:イテレータはバイトではなく文字列を返すべき
-
[解決済み】syntaxError: 'continue' がループ内で適切に使用されていない