私はユーザーからの入力を受け付けなければならないプログラムを書いています。
#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およびcatch を使用します。
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
上記の手法は両方とも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:
print(template.format(" or ".join((", ".join(map(str,
range_[:-1])),
str(range_[-1])))))
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
メソッドよりも短いからです。しかし、それはソフトウェア開発の Don't Repeat Yourself の原則に違反します。これはあなたのシステムのバグの可能性を高めます。 input
をraw_input
に変更して2.7にバックポートしたいが、誤って上記の最初の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
で終了します。あなたは「愚か者が連続して1000の失敗をすることはないだろう」と思うかもしれませんが、あなたは愚か者の創意工夫を過小評価しています!
あなたがwhile True
を実行してからこのループから抜け出す一方で、あなたが望むものは年齢が決まったらやめることなので、あなたはちょうどwhileステートメントにあなたの要件を入れることもできるのでしょうか?
age = None
while age is None:
input_value = input("Please enter your age: ")
try:
# try and convert the string input to a number
age = int(input_value)
except ValueError:
# tell the user off
print("{input} is not a number, please enter a number only".format(input=input_value))
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.")
これにより、次のようになります。
Please enter your age: *potato*
potato is not a number, please enter a number only
Please enter your age: *5*
You are not able to vote in the United States.
年齢が意味をなさない値を持つことは決してなく、コードはあなたの「ビジネスプロセス」の論理に従うので、これはうまくいくでしょう。
受け入れられた答えは素晴らしいですが。この問題に対する簡単なハックも共有したいと思います。 (これは同様に負の年齢問題を世話します。)
f=lambda age: (age.isdigit() and ((int(age)>=18 and "Can vote" ) or "Cannot vote")) or \
f(input("invalid input. Try again\nPlease enter your age: "))
print(f(input("Please enter your age: ")))
P.Sこのコードはpython 3.x用です。
それで、私は最近これに似た何かをいじっていました、そしてそれがどんな論理的な方法でもチェックされる前に、がらくたを拒絶する入力を得る方法を使う以下の解決策を思いつきました。
read_single_keypress()
礼儀 https://stackoverflow.com/a/6599441/4532996
def read_single_keypress() -> str:
"""Waits for a single keypress on stdin.
-- from :: https://stackoverflow.com/a/6599441/4532996
"""
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# save old state
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# make raw - the way to do this comes from the termios(3) man page.
attrs = list(attrs_save) # copy the stored version to update
# iflag
attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
| termios.ISTRIP | termios.INLCR | termios. IGNCR
| termios.ICRNL | termios.IXON )
# oflag
attrs[1] &= ~termios.OPOST
# cflag
attrs[2] &= ~(termios.CSIZE | termios. PARENB)
attrs[2] |= termios.CS8
# lflag
attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
| termios.ISIG | termios.IEXTEN)
termios.tcsetattr(fd, termios.TCSANOW, attrs)
# turn off non-blocking
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# read a single keystroke
try:
ret = sys.stdin.read(1) # returns a single character
except KeyboardInterrupt:
ret = 0
finally:
# restore old state
termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return ret
def until_not_multi(chars) -> str:
"""read stdin until !(chars)"""
import sys
chars = list(chars)
y = ""
sys.stdout.flush()
while True:
i = read_single_keypress()
_ = sys.stdout.write(i)
sys.stdout.flush()
if i not in chars:
break
y += i
return y
def _can_you_vote() -> str:
"""a practical example:
test if a user can vote based purely on keypresses"""
print("can you vote? age : ", end="")
x = int("0" + until_not_multi("0123456789"))
if not x:
print("\nsorry, age can only consist of digits.")
return
print("your age is", x, "\nYou can vote!" if x >= 18 else "Sorry! you can't vote")
_can_you_vote()
完全なモジュール ここ を見つけることができます。
例:
$ ./input_constrain.py
can you vote? age : a
sorry, age can only consist of digits.
$ ./input_constrain.py
can you vote? age : 23<RETURN>
your age is 23
You can vote!
$ _
この実装の性質は、数字ではないものが読み込まれるとすぐに標準入力を閉じることです。 a
の後でenterを押していませんでしたが、数字の後を押す必要がありました。
これを同じモジュールのthismany()
関数とマージして、たとえば3桁の数字だけを許可することができます。
def validate_age(age):
if age >=0 :
return True
return False
while True:
try:
age = int(raw_input("Please enter your age:"))
if validate_age(age): break
except ValueError:
print "Error: Invalid age."
コードを編集してエラーを修正するには
while True:
try:
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
break
else:
print("You are not able to vote in the United States.")
break
except ValueError:
print("Please enter a valid response")
Daniel QとPatrick Artnerの優れた提案に基づいて、さらに一般化されたソリューションを紹介します。
# Assuming Python3
import sys
class ValidationError(ValueError): # thanks Patrick Artner
pass
def validate_input(Prompt, cast=str, cond=(lambda x: True), onerror=None):
if onerror==None: onerror = {}
while True:
try:
data = cast(input(Prompt))
if not cond(data): raise ValidationError
return data
except Tuple(onerror.keys()) as e: # thanks Daniel Q
print(onerror[type(e)], file=sys.stderr)
堅牢性を提供するために検証を常にオンにする必要があるのに対して、アサーションチェックはオフにすることができるので、if
ではなく明示的なraise
およびassert
ステートメントを選択しました。
これは、検証条件が異なる、さまざまな種類の入力を取得するために使用できます。例えば:
# No validation, equivalent to simple input:
anystr = validate_input("Enter any string: ")
# Get a string containing only letters:
letters = validate_input("Enter letters: ",
cond=str.isalpha,
onerror={ValidationError: "Only letters, please!"})
# Get a float in [0, 100]:
percentage = validate_input("Percentage? ",
cast=float, cond=lambda x: 0.0<=x<=100.0,
onerror={ValidationError: "Must be between 0 and 100!",
ValueError: "Not a number!"})
または、元の質問に答えるには:
age = validate_input("Please enter your age: ",
cast=int, cond=lambda a:0<=a<150,
onerror={ValidationError: "Enter a plausible age, please!",
ValueError: "Enter an integer, please!"})
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.")
ユーザーが真の値を入力し、入力値が数値でないかヌル値である場合は "while"ステートメントを使用し、それをスキップしてもう一度尋ねてください。例では、私は本当にあなたの質問に答えようとしました。私たちの年齢が1歳から150歳の間にあるとすると入力値は受け入れられますが、そうでなければそれは間違った値です。プログラムを終了するために、ユーザーは0キーを使用して値として入力することができます。
注:コードの先頭にあるコメントを読んでください。
# If your input value is only a number then use "Value.isdigit() == False".
# If you need an input that is a text, you should remove "Value.isdigit() == False".
def Input(Message):
Value = None
while Value == None or Value.isdigit() == False:
try:
Value = str(input(Message)).strip()
except InputError:
Value = None
return Value
# Example:
age = 0
# If we suppose that our age is between 1 and 150 then input value accepted,
# else it's a wrong value.
while age <=0 or age >150:
age = int(Input("Please enter your age: "))
# For terminating program, the user can use 0 key and enter it as an a value.
if age == 0:
print("Terminating ...")
exit(0)
if age >= 18 and age <=150:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
この方法を試してください。 -
def takeInput(required):
print 'ooo or OOO to exit'
ans = raw_input('Enter: ')
if not ans:
print "You entered nothing...!"
return takeInput(required)
## FOR Exit ##
Elif ans in ['ooo', 'OOO']:
print "Closing instance."
exit()
else:
if ans.isdigit():
current = 'int'
Elif set('[~!@#$%^&*()_+{}":/\']+$').intersection(ans):
current = 'other'
Elif isinstance(ans,basestring):
current = 'str'
else:
current = 'none'
if required == current :
return ans
else:
return takeInput(required)
## pass the value in which type you want [str/int/special character(as other )]
print "input: ", takeInput('str')
Clickはコマンドラインインターフェイス用のライブラリであり、ユーザーから有効な応答を求めるための機能を提供します。
簡単な例:
number = click.Prompt('Please enter a number', type=float)
print(number)
Please enter a number:
a
Error: a is not a valid floating point value
Please enter a number:
10
10.0
文字列値を自動的にfloatに変換する方法に注意してください。
異なる カスタム型 があります。特定の範囲の数値を取得するには、IntRange
を使用します。
age = click.Prompt("What's your age?", type=click.IntRange(1, 120))
print(age)
What's your age?:
a
Error: a is not a valid integer
What's your age?:
0
Error: 0 is not in the valid range of 1 to 120.
What's your age?:
5
5
min
またはmax
のいずれかの制限を指定することもできます。
age = click.Prompt("What's your age?", type=click.IntRange(min=14))
print(age)
What's your age?:
0
Error: 0 is smaller than the minimum valid value 14.
What's your age?:
18
18
click.Choice
型を使用します。デフォルトでは、このチェックでは大文字と小文字が区別されます。
choices = {'Apple', 'orange', 'Peach'}
choice = click.Prompt('Provide a fruit', type=click.Choice(choices, case_sensitive=False))
print(choice)
Provide a fruit (Apple, Peach, orange):
banana
Error: invalid choice: banana. (choose from Apple, Peach, orange)
Provide a fruit (Apple, Peach, orange):
OrAnGe
orange
click.Path
型を使用して、既存のパスを確認し、それらを解決することもできます。
path = click.Prompt('Provide path', type=click.Path(exists=True, resolve_path=True))
print(path)
Provide path:
nonexistent
Error: Path "nonexistent" does not exist.
Provide path:
existing_folder
'/path/to/existing_folder
ファイルの読み書きはclick.File
で行えます。
file = click.Prompt('In which file to write data?', type=click.File('w'))
with file.open():
file.write('Hello!')
# More info about `lazy=True` at:
# https://click.palletsprojects.com/en/7.x/arguments/#file-opening-safety
file = click.Prompt('Which file you wanna read?', type=click.File(lazy=True))
with file.open():
print(file.read())
In which file to write data?:
# <-- provided an empty string, which is an illegal name for a file
In which file to write data?:
some_file.txt
Which file you wanna read?:
nonexistent.txt
Error: Could not open file: nonexistent.txt: No such file or directory
Which file you wanna read?:
some_file.txt
Hello!
password = click.Prompt('Enter password', hide_input=True, confirmation_Prompt=True)
print(password)
Enter password:
······
Repeat for confirmation:
·
Error: the two entered values do not match
Enter password:
······
Repeat for confirmation:
······
qwerty
この場合は、単に押すだけです。 Enter 値を入力せずに(またはあなたが使用するどんなキーでも)、あなたにデフォルトのものを与えるでしょう:
number = click.Prompt('Please enter a number', type=int, default=42)
print(number)
Please enter a number [42]:
a
Error: a is not a valid integer
Please enter a number [42]:
42
同じユースケースが多くの現実のアプリケーションで発生するので、ユーザーが特定の回数だけ入力することを可能にするためにもっと一般的なロジックを書くことができます。
def getValidInt(iMaxAttemps = None):
iCount = 0
while True:
# exit when maximum attempt limit has expired
if iCount != None and iCount > iMaxAttemps:
return 0 # return as default value
i = raw_input("Enter no")
try:
i = int(i)
except ValueError as e:
print "Enter valid int value"
else:
break
return i
age = getValidInt()
# do whatever you want to do.
良い質問!あなたはこれのために次のコードを試すことができます。 =)
このコードでは ast.literal_eval() を使用して 入力のデータ型を検索します (age
)。その後、次のアルゴリズムに従います。
ユーザーに
age
を入力するように依頼します。1.1。
age
がfloat
またはint
データ型の場合
age>=18
がないか確認してください。age>=18
の場合、適切な出力を表示して終了します。
0<age<18
がないか確認してください。0<age<18
の場合、適切な出力を表示して終了します。
age<=0
の場合は、年齢に有効な数値をもう一度入力するようにユーザーに依頼します(すなわちは手順1に戻ります)。1.2。
age
がfloat
またはint
データ型ではない場合は、ユーザーに年齢を再入力するように依頼します(ieは手順1に戻ります)
これがコードです。
from ast import literal_eval
''' This function is used to identify the data type of input data.'''
def input_type(input_data):
try:
return type(literal_eval(input_data))
except (ValueError, SyntaxError):
return str
flag = True
while(flag):
age = raw_input("Please enter your age: ")
if input_type(age)==float or input_type(age)==int:
if eval(age)>=18:
print("You are able to vote in the United States!")
flag = False
Elif eval(age)>0 and eval(age)<18:
print("You are not able to vote in the United States.")
flag = False
else: print("Please enter a valid number as your age.")
else: print("Sorry, I didn't understand that.")
try
/except
ブロックは機能しますが、このタスクを達成するためのはるかに速くてきれいな方法はstr.isdigit()
を使うことです。
while True:
age = input("Please enter your age: ")
if age.isdigit():
age = int(age)
break
else:
print("Invalid number '{age}'. Try again.".format(age=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.")
再帰関数 :を使用した持続的なユーザー入力
def askName():
return input("Write your name: ").strip() or askName()
name = askName()
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
そして最後に、質問の要件:
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
responseAge = [
"You are able to vote in the United States!",
"You are not able to vote in the United States.",
][int(age < 18)]
print(responseAge)
from itertools import chain, repeat
prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies))
print(valid_response)
Enter a number: a
Not a number! Try again: b
Not a number! Try again: 1
1
または、他の回答のように入力プロンプトから「不正な入力」メッセージを分離したい場合は、
Prompt_msg = "Enter a number: "
bad_input_msg = "Sorry, I didn't understand that."
prompts = chain([Prompt_msg], repeat('\n'.join([bad_input_msg, Prompt_msg])))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies))
print(valid_response)
Enter a number: a
Sorry, I didn't understand that.
Enter a number: b
Sorry, I didn't understand that.
Enter a number: 1
1
prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
この itertools.chain
と itertools.repeat
の組み合わせは、文字列"Enter a number: "
を1回生成し、"Not a number! Try again: "
を無限回生成する反復子を作成します。for Prompt in prompts:
print(Prompt)
Enter a number:
Not a number! Try again:
Not a number! Try again:
Not a number! Try again:
# ... and so on
replies = map(input, prompts)
- here map
は前のステップからのすべてのprompts
文字列を input
関数に適用します。例えば。:for reply in replies:
print(reply)
Enter a number: a
a
Not a number! Try again: 1
1
Not a number! Try again: it doesn't care now
it doesn't care now
# and so on...
filter
と str.isdigit
を使用します。only_digits = filter(str.isdigit, replies)
for reply in only_digits:
print(reply)
Enter a number: a
Not a number! Try again: 1
1
Not a number! Try again: 2
2
Not a number! Try again: b
Not a number! Try again: # and so on...
そして最初の数字のみの文字列を取得するには next
を使います。 文字列メソッド: もちろん、 str.isalpha
のような他の文字列メソッドを使用してアルファベット文字列のみを取得したり、 str.isupper
を使用して大文字のみを取得したりできます。完全なリストは docs を見てください。
会員テスト:
それを実行する方法はいくつかあります。その1つは __contains__
メソッドを使うことです。
from itertools import chain, repeat
fruits = {'Apple', 'orange', 'Peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
valid_response = next(filter(fruits.__contains__, replies))
print(valid_response)
Enter a fruit: 1
I don't know this one! Try again: foo
I don't know this one! Try again: Apple
apple
数字の比較:
ここで使用できる便利な比較方法があります。たとえば、 __lt__
(<
)の場合、次のようになります。
from itertools import chain, repeat
prompts = chain(["Enter a positive number:"], repeat("I need a positive number! Try again:"))
replies = map(input, prompts)
numeric_strings = filter(str.isnumeric, replies)
numbers = map(float, numeric_strings)
is_positive = (0.).__lt__
valid_response = next(filter(is_positive, numbers))
print(valid_response)
Enter a positive number: a
I need a positive number! Try again: -5
I need a positive number! Try again: 0
I need a positive number! Try again: 5
5.0
あるいは、それが気に入らない場合は、常に独自の関数を定義するか、または operator
モジュールの関数を使用することができます。
パスの存在:
ここではpathlib
ライブラリとその Path.exists
メソッドを使うことができます。
from itertools import chain, repeat
from pathlib import Path
prompts = chain(["Enter a path: "], repeat("This path doesn't exist! Try again: "))
replies = map(input, prompts)
paths = map(Path, replies)
valid_response = next(filter(Path.exists, paths))
print(valid_response)
Enter a path: a b c
This path doesn't exist! Try again: 1
This path doesn't exist! Try again: existing_file.txt
existing_file.txt
無限の回数何かを尋ねてユーザーを拷問したくない場合は、 itertools.repeat
の呼び出しで制限を指定できます。これは next
関数にデフォルト値を与えることと組み合わせることができます。
from itertools import chain, repeat
prompts = chain(["Enter a number:"], repeat("Not a number! Try again:", 2))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies), None)
print("You've failed miserably!" if valid_response is None else 'Well done!')
Enter a number: a
Not a number! Try again: b
Not a number! Try again: c
You've failed miserably!
例えば、プログラムが1歳から120歳までの年齢を尋ねる場合など、単純なケースでは、別のfilter
を追加するだけです。
from itertools import chain, repeat
Prompt_msg = "Enter your age (1-120): "
bad_input_msg = "Wrong input."
prompts = chain([Prompt_msg], repeat('\n'.join([bad_input_msg, Prompt_msg])))
replies = map(input, prompts)
numeric_replies = filter(str.isdigit, replies)
ages = map(int, numeric_replies)
positive_ages = filter((0).__lt__, ages)
not_too_big_ages = filter((120).__ge__, positive_ages)
valid_response = next(not_too_big_ages)
print(valid_response)
しかし、多くの規則がある場合は、 論理積 を実行する関数を実装する方が適切です。次の例では、 here の中から準備したものを使います。
from functools import partial
from itertools import chain, repeat
from lz.logical import conjoin
def is_one_letter(string: str) -> bool:
return len(string) == 1
rules = [str.isalpha, str.isupper, is_one_letter, 'C'.__le__, 'P'.__ge__]
Prompt_msg = "Enter a letter (C-P): "
bad_input_msg = "Wrong input."
prompts = chain([Prompt_msg], repeat('\n'.join([bad_input_msg, Prompt_msg])))
replies = map(input, prompts)
valid_response = next(filter(conjoin(*rules), replies))
print(valid_response)
Enter a letter (C-P): 5
Wrong input.
Enter a letter (C-P): f
Wrong input.
Enter a letter (C-P): CDE
Wrong input.
Enter a letter (C-P): Q
Wrong input.
Enter a letter (C-P): N
N
残念ながら、失敗したケースごとにカスタムメッセージが必要な場合は、きれいな機能的な方法はありません)。
Whileループを終了しないでtry catchを使用してください。空白文字列をチェックするには、IFステートメントを使用して文字列が空かどうかを確認します。
while True:
name = input("Enter Your Name\n")
if not name:
print("I did not understood that")
continue
else:
break
while True:
try:
salary = float(input("whats ur salary\n"))
except ValueError:
print("I did not understood that")
continue
else:
break
while True:
try:
print("whats ur age?")
age = int(float(input()))
except ValueError:
print("I did not understood that")
continue
else:
break
print("Hello "+ name + "\nYour salary is " + str(salary) + '\nand you will be ' + str(age+1) +' in a Year')
これは、繰り返しのif/elseブロックを回避する、よりクリーンでより一般化された解決策です。(Error、error Prompt)のペアを辞書に取り、すべての値チェックをアサーションで行う関数を作成します。
def validate_input(Prompt, error_map):
while True:
try:
data = int(input(Prompt))
# Insert your non-exception-throwing conditionals here
assert data > 0
return data
# Print whatever text you want the user to see
# depending on how they messed up
except Tuple(error_map.keys()) as e:
print(error_map[type(e)])
使用法:
d = {ValueError: 'Integers only', AssertionError: 'Positive numbers only',
KeyboardInterrupt: 'You can never leave'}
user_input = validate_input("Positive number: ", d)
整数入力に対してカスタマイズされたValidationError
および(オプションの)範囲検証を使用して入力検証を使用するためのもう1つの解決策:
class ValidationError(ValueError):
"""Special validation error - its message is supposed to be printed"""
pass
def RangeValidator(text,num,r):
"""Generic validator - raises 'text' as ValidationError if 'num' not in range 'r'."""
if num in r:
return num
raise ValidationError(text)
def ValidCol(c):
"""Specialized column validator providing text and range."""
return RangeValidator("Columns must be in the range of 0 to 3 (inclusive)",
c, range(4))
def ValidRow(r):
"""Specialized row validator providing text and range."""
return RangeValidator("Rows must be in the range of 5 to 15(exclusive)",
r, range(5,15))
使用法:
def GetInt(text, validator=None):
"""Aks user for integer input until a valid integer is given. If provided,
a 'validator' function takes the integer and either raises a
ValidationError to be printed or returns the valid number.
Non integers display a simple error message."""
print()
while True:
n = input(text)
try:
n = int(n)
return n if validator is None else validator(n)
except ValueError as ve:
# prints ValidationErrors directly - else generic message:
if isinstance(ve, ValidationError):
print(ve)
else:
print("Invalid input: ", n)
column = GetInt("Pleased enter column: ", ValidCol)
row = GetInt("Pleased enter row: ", ValidRow)
print( row, column)
出力:
Pleased enter column: 22
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: -2
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: 2
Pleased enter row: a
Invalid input: a
Pleased enter row: 72
Rows must be in the range of 5 to 15(exclusive)
Pleased enter row: 9
9, 2
有効な番号を入力するまで、ユーザーに番号の入力を求めます。
#note: Python 2.7 users should use raw_input, the equivalent of 3.X's input
while(1):
try:
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
break()
else:
print("You are not able to vote in the United States.")
break()
except:
print("Please only enter numbers ")
単純なif-elseロジックをいつでも適用でき、if
ループとともにコードにもう1つのfor
ロジックを追加できます。
while True:
age = int(input("Please enter your age: "))
if (age >= 18) :
print("You are able to vote in the United States!")
if (age < 18) & (age > 0):
print("You are not able to vote in the United States.")
else:
print("Wrong characters, the input must be numeric")
continue
これは無限の手段であり、無期限に年齢を入力するように求められます。
入力ステートメントをwhile Trueループにして、ユーザー入力を繰り返し要求し、ユーザーが希望する応答を入力した場合はそのループを中断することができます。そして、tryおよびexceptブロックを使用して無効な応答を処理できます。
while True:
var = True
try:
age = int(input("Please enter your age: "))
except ValueError:
print("Invalid input.")
var = False
if var == True:
if age >= 18:
print("You are able to vote in the United States.")
break
else:
print("You are not able to vote in the United States.")
Var変数は、ユーザーが整数の代わりに文字列を入力した場合に、プログラムが「あなたはアメリカで投票することはできません」を返さないということです。