有効な応答が得られるまでユーザーに入力を求める

609
Kevin 2014-04-26 03:31.

ユーザーからの入力を受け入れるプログラムを書いています。

#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が、このコンテキストでは無意味です。

15 answers

776
Kevin 2014-04-26 03:31.

これを実現する最も簡単な方法は、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

例外処理とカスタム検証の組み合わせ

上記の両方の手法を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メソッドよりも短いので魅力的に見えるかもしれませんが、ソフトウェア開発の「Do n'tRepeatYourself」の原則に違反しています。これにより、システムにバグが発生する可能性が高くなります。に変更inputして2.7にバックポートしたい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。で終了します。「愚か者が1000回連続でミスを犯すことはない」と思うかもしれませんが、愚か者の創意工夫を過小評価しています!

46
Steven Stip 2016-01-15 02:43.

while True年齢が決まったら停止するだけなので、whileステートメントに要件を含めることもできますが、なぜaを実行してから、このループから抜け出すのでしょうか。

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.

年齢には意味のない値がなく、コードは「ビジネスプロセス」のロジックに従うため、これは機能します。

26
aaveg 2015-06-29 13:29.

受け入れられた答えは素晴らしいですが。また、この問題の簡単なハックを共有したいと思います。(これにより、負の年齢の問題も処理されます。)

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: ")))

PSこのコードはPython3.x用です。

17
Georgy 2019-05-11 06:47.

機能的アプローチまたは「ループがないように見える!」:

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

それはどのように機能しますか?

  1. prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
    
    とのこの組み合わせによりitertools.chainitertools.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
    
  2. replies = map(input, prompts)-ここでmapprompts、前の手順のすべての文字列を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...
    
  3. を使用してfilterstr.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

その他の検証ルール:

  1. 文字列メソッド:もちろんstr.isalpha、アルファベットの文字列str.isupperのみを取得したり、大文字のみを取得したりするなど、他の文字列メソッドを使用できます。完全なリストについては、ドキュメントを参照してください。

  2. メンバーシップテスト:
    それを実行するには、いくつかの異なる方法があります。それらの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
    
  3. 数値の比較:
    ここで使用できる便利な比較方法があります。たとえば、__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
    

    または、dunderメソッド(dunder = double-underscore)を使用したくない場合は、いつでも独自の関数を定義するか、operatorモジュールの関数を使用できます。

  4. パスの存在:
    ここでは、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!

入力データの前処理:

ユーザーが誤って提供されている場合時々 、入力を拒否したくないCAPS INまたは文字列の先頭または末尾にスペースを。これらの単純な間違いを考慮に入れるためにstr.lowerstr.stripメソッドを適用して入力データを前処理することができます。たとえば、メンバーシップテストの場合、コードは次のようになります。

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)
lowercased_replies = map(str.lower, replies)
stripped_replies = map(str.strip, lowercased_replies)
valid_response = next(filter(fruits.__contains__, stripped_replies))
print(valid_response)
Enter a fruit:  duck
I don't know this one! Try again:     Orange
orange

前処理に使用する関数が多い場合は、関数合成を実行する関数を使用する方が簡単な場合があります。たとえば、ここからのものを使用します

from itertools import chain, repeat

from lz.functional import compose

fruits = {'apple', 'orange', 'peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
process = compose(str.strip, str.lower)  # you can add more functions here
processed_replies = map(process, replies)
valid_response = next(filter(fruits.__contains__, processed_replies))
print(valid_response)
Enter a fruit:  potato
I don't know this one! Try again:   PEACH
peach

検証ルールの組み合わせ:

単純なケースの場合、たとえば、プログラムが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)

ただし、ルールが多い場合は、論理積を実行する関数を実装することをお勧めします。次の例では、ここから準備ができたものを使用します

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

残念ながら、誰かが失敗した各ケースのためのカスタムメッセージを必要とする場合、その後、私は怖い、何もありませんかなり機能的な方法は。または、少なくとも、私はそれを見つけることができませんでした。

13
cat 2016-01-31 17:47.

それで、私は最近これに似たものをいじっていました、そしてそれが論理的な方法でさえチェックされる前に、ジャンクを拒絶する入力を得る方法を使用する次の解決策を思いつきました。

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!
$ _

この実装の性質は、数字ではないものが読み取られるとすぐにstdinを閉じることであることに注意してください。後aにEnterキーを押しませんでしたが、数字の後に入力する必要がありました。

これをthismany()同じモジュール内の関数とマージして、たとえば3桁のみを許可することができます。

12
Georgy 2019-05-11 10:17.

クリックの使用:

Clickは、コマンドラインインターフェイス用のライブラリであり、ユーザーに有効な応答を求める機能を提供します。

簡単な例:

import 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

制限の1つだけを指定することもできます、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
3
ojas mohril 2016-06-24 00:34.
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."
2
João Manuel Rodrigues 2018-11-29 04:52.

DanielQとPatrickArtnerの優れた提案に基づいて、さらに一般化されたソリューションを次に示します。

# 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)

アサーションチェックがオフになっている可能性があるのに対し、堅牢性を提供するには検証を常にオンにする必要があるため、の代わりに明示的なステートメントifraiseステートメントを選択しました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.")
1
Pratik Anand 2017-04-30 23:29.

これを試してください:-

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('[[email protected]#$%^&*()_+{}":/\']+$').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')
1
np8 2020-10-30 21:12.

ええ、私は🎉から6年遅れていますが、この質問はより最新の回答に値します。

関心事の分離

私はUnix哲学「1つのことをしてうまくやる」の大ファンです。このタイプの問題では、問題を次のように分割することをお勧めします。

  • 入力を依頼get_input入力がOKになるまで。
  • validator関数で検証します。入力クエリごとに異なるバリデーターを作成できます。

入力を求める

(Python 3+)と同じくらいシンプルに保つことができます

def myvalidator(value):
    try:
        value = int(value)
    except ValueError:
        return False
    return value >= 0

def get_input(prompt, validator, on_validationerror):
    while True:
        value = input(prompt)
        if validator(value):
            return value
        print(on_validationerror)

In [2]: get_input('Give a positive number: ', myvalidator, 'Please, try again')
Give a positive number: foobar
Please, try again
Give a positive number: -10
Please, try again
Give a positive number: 42
Out[2]: '42'

Python3.8 +注

Python 3.8以降では、セイウチ演算子を使用できます

def get_input(prompt, validator, on_validationerror):
    while not validator(value := input(prompt)):
        print(on_validationerror)
    return value 
0
2Cubed 2016-05-31 10:47.

一方で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.")
0
Siddharth Satpathy 2018-12-18 20:17.

良い質問!これには、次のコードを試すことができます。=)

このコードは、ast.literal_eval()を使用して、入力age)のデータ型検索します。次に、次のアルゴリズムに従います。

  1. ユーザーに入力を求めますage

    1.1。ageisfloatまたはintデータ型の場合:

    • かどうかを確認しますage>=18。の場合age>=18、適切な出力を出力して終了します。

    • かどうかを確認します0<age<18。の場合0<age<18、適切な出力を出力して終了します。

    • の場合age<=0、年齢の有効な数値をもう一度入力するようにユーザーに依頼します(つまり、手順1に戻ります)。

    1.2。そうageでないfloatか、intデータ型の場合は、ユーザーに年齢をもう一度入力するように依頼します(つまり、手順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.") 
0
Ep1c1aN 2019-07-01 23:36.

いつでも単純なif-elseロジックを適用ifし、forループとともにコードにもう1つのロジックを追加できます。

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

これは無限のルーになり、あなたは無期限に時代を入力するように求められます。

0
Liju 2020-08-17 22:24.

以下のコードが役立つ場合があります。

age=(lambda i,f: f(i,f))(input("Please enter your age: "),lambda i,f: i if i.isdigit() else f(input("Please enter your age: "),f))
print("You are able to vote in the united states" if int(age)>=18 else "You are not able to vote in the united states",end='')

最大試行回数、たとえば3回の試行が必要な場合は、以下のコードを使用してください

age=(lambda i,n,f: f(i,n,f))(input("Please enter your age: "),1,lambda i,n,f: i if i.isdigit() else (None if n==3 else f(input("Please enter your age: "),n+1,f)))
print("You are able to vote in the united states" if age and int(age)>=18 else "You are not able to vote in the united states",end='')

注:これは再帰を使用します。

0
behnaz.sheikhi 2020-09-10 02:30.

try-exceptを使用してエラーを処理し、もう一度繰り返します。

while True:
    try:
        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.")
    except Exception as e:
        print("please enter number")

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

世界最小のマルチツールを15ドルでキーチェーンに追加

世界最小のマルチツールを15ドルでキーチェーンに追加

爪| $ 15 | マルボロ&ケインザクロー| $ 15 | Malboro&Kane世界最小のマルチツールであるTheClawをたった15ドルで手に入れましょう。男の子と一緒に冷たいものを割って開けたり、ネジを締めたり、Amazonパッケージを細断したりする場合でも、この悪い男の子はこれまでで最も便利な製品の1つです。

ワンダーウーマンの続編の悪役についてのより多くの噂

ワンダーウーマンの続編の悪役についてのより多くの噂

ワンダーウーマンとしてのガル・ガドット。WaywardPinesは正式に終了しました。

42,000試合で作られた球がスローモーションで燃えるのを見るのは魅力的な光景です

42,000試合で作られた球がスローモーションで燃えるのを見るのは魅力的な光景です

人が2つのマッチを接着するように導くものは何ですか?何があなたをマッチに打ち続け、構造が湾曲していることを発見するのですか?42,000のボールを作るまで、試合を続けなければならない理由は何ですか?しかし、何よりも、これほど魅力的なショーである可能性はどのようにありますか?私はあなたをだますつもりはありません、次に私たちがあなたに残すのは、あなたや私のような人が自由な時間を過ごすことを決定するビデオですボールを作るために必要な試合数を確認します(答えは42です。

サクラメントビーが1950万人のカリフォルニア州の有権者記録を漏らし、ハッカーによって即座に侵害された

サクラメントビーが1950万人のカリフォルニア州の有権者記録を漏らし、ハッカーによって即座に侵害された

写真:AP先月、カリフォルニアの地元新聞が1,900万件以上の有権者記録をオンラインで公開しました。Gizmodoは今週、明らかなランサムウェア攻撃中にレコードが侵害されたことを確認しました。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language