Meminta masukan dari pengguna sampai mereka memberikan tanggapan yang valid

Apr 25 2014

Saya menulis program yang menerima masukan dari pengguna.

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

Program bekerja seperti yang diharapkan selama pengguna memasukkan data yang berarti.

C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!

Tetapi gagal jika pengguna memasukkan data yang tidak valid:

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'

Alih-alih mogok, saya ingin program meminta masukan lagi. Seperti ini:

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!

Bagaimana saya bisa membuat program meminta masukan yang valid alih-alih berhenti bekerja saat data non-sensorik dimasukkan?

Bagaimana saya bisa menolak nilai seperti -1, mana yang valid int, tapi tidak masuk akal dalam konteks ini?

Jawaban

776 Kevin Apr 25 2014 at 20:31

Cara termudah untuk melakukannya adalah dengan menempatkan inputmetode dalam loop sementara. Gunakan continuesaat Anda mendapatkan masukan yang buruk, dan breakkeluar dari lingkaran saat Anda puas.

Saat Masukan Anda Mungkin Menimbulkan Pengecualian

Gunakan trydanexcept untuk mendeteksi saat pengguna memasukkan data yang tidak dapat diurai.

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

Menerapkan Aturan Validasi Anda Sendiri

Jika Anda ingin menolak nilai yang berhasil diurai Python, Anda dapat menambahkan logika validasi Anda sendiri.

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

Menggabungkan Penanganan Pengecualian dan Validasi Kustom

Kedua teknik di atas dapat digabungkan menjadi satu loop.

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

Mengenkapsulasi Semuanya dalam Fungsi

Jika Anda perlu meminta banyak nilai yang berbeda kepada pengguna, mungkin berguna untuk meletakkan kode ini dalam sebuah fungsi, jadi Anda tidak perlu mengetik ulang setiap saat.

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

Menyatukan Semuanya

Anda dapat memperluas ide ini untuk membuat fungsi masukan yang sangat umum:

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

Dengan penggunaan seperti:

age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))

Kesulitan Umum, dan Mengapa Anda Harus Menghindarinya

Penggunaan inputPernyataan Redundan

Metode ini berfungsi tetapi umumnya dianggap gaya yang buruk:

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

Ini mungkin terlihat menarik pada awalnya karena lebih pendek daripada while Truemetodenya, tetapi itu melanggar prinsip Don't Repeat Yourself dalam pengembangan perangkat lunak. Ini meningkatkan kemungkinan bug di sistem Anda. Bagaimana jika Anda ingin mem-backport ke 2.7 dengan mengubah inputke raw_input, tetapi secara tidak sengaja hanya mengubah yang pertama di inputatas? Ini SyntaxErrorhanya menunggu untuk terjadi.

Rekursi Akan Meledakkan Stack Anda

Jika Anda baru saja belajar tentang rekursi, Anda mungkin tergoda untuk menggunakannya get_non_negative_intsehingga Anda dapat membuang while loop.

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

Ini tampaknya berfungsi dengan baik sebagian besar waktu, tetapi jika pengguna memasukkan data yang tidak valid cukup sering, skrip akan diakhiri dengan RuntimeError: maximum recursion depth exceeded. Anda mungkin berpikir "tidak ada orang bodoh yang akan membuat 1000 kesalahan berturut-turut", tetapi Anda meremehkan kecerdikan orang bodoh!

46 StevenStip Jan 14 2016 at 19:43

Mengapa Anda melakukan a while Truedan kemudian keluar dari lingkaran ini sementara Anda juga dapat memasukkan persyaratan Anda dalam pernyataan while karena yang Anda inginkan hanyalah berhenti setelah Anda cukup umur?

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

Ini akan menghasilkan yang berikut:

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.

ini akan berhasil karena usia tidak akan pernah memiliki nilai yang tidak masuk akal dan kode mengikuti logika "proses bisnis" Anda

26 aaveg Jun 29 2015 at 06:29

Padahal jawaban yang diterima luar biasa. Saya juga ingin membagikan retasan cepat untuk masalah ini. (Ini juga menangani masalah usia negatif.)

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 Kode ini untuk python 3.x.

17 Georgy May 10 2019 at 23:47

Pendekatan fungsional atau " look mum no loops! ":

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

atau jika Anda ingin memiliki pesan "masukan buruk" yang dipisahkan dari prompt masukan seperti pada jawaban lain:

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

Bagaimana cara kerjanya?

  1. prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
    
    Kombinasi itertools.chaindan itertools.repeatakan membuat iterator yang akan menghasilkan string "Enter a number: "sekali, dan "Not a number! Try again: "dalam jumlah tak terbatas:
    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)- di sini mapakan menerapkan semua promptsstring dari langkah sebelumnya ke inputfungsi. Misalnya:
    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. Kami menggunakan filterdan str.isdigituntuk menyaring string yang hanya berisi angka:
    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...
    
    Dan untuk mendapatkan hanya digit pertama saja kita gunakan string next.

Aturan validasi lainnya:

  1. Metode string: Tentu saja Anda dapat menggunakan metode string lain seperti str.isalphahanya mendapatkan string alfabetis, atau str.isupperhanya mendapatkan huruf besar. Lihat dokumen untuk daftar lengkapnya.

  2. Pengujian keanggotaan:
    Ada beberapa cara berbeda untuk melakukannya. Salah satunya adalah dengan menggunakan __contains__metode:

    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. Perbandingan angka:
    Ada metode perbandingan berguna yang dapat kita gunakan di sini. Misalnya, untuk __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
    

    Atau, jika Anda tidak suka menggunakan metode dunder (dunder = double-underscore), Anda selalu dapat menentukan fungsi Anda sendiri, atau menggunakan yang dari operatormodul.

  4. Keberadaan jalur:
    Di sini seseorang dapat menggunakan pathlibpustaka dan Path.existsmetodenya:

    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
    

Membatasi jumlah percobaan:

Jika Anda tidak ingin menyiksa pengguna dengan menanyakan sesuatu berkali-kali, Anda dapat menentukan batas dalam panggilan itertools.repeat. Ini dapat dikombinasikan dengan memberikan nilai default ke nextfungsi:

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!

Memproses data masukan:

Terkadang kami tidak ingin menolak input jika pengguna secara tidak sengaja memasukkannya DALAM HURUF BESAR atau dengan spasi di awal atau akhir string. Untuk memperhitungkan kesalahan sederhana ini, kita dapat memproses data input dengan menerapkan str.lowerdan str.stripmetode. Misalnya, untuk kasus pengujian keanggotaan, kode akan terlihat seperti ini:

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

Jika Anda memiliki banyak fungsi yang akan digunakan untuk praproses, mungkin lebih mudah menggunakan fungsi yang menjalankan komposisi fungsi . Misalnya, menggunakan yang dari sini :

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

Menggabungkan aturan validasi:

Untuk kasus sederhana, misalnya, ketika program meminta usia antara 1 dan 120, seseorang dapat menambahkan yang lain 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)

Namun jika ada banyak aturan, lebih baik mengimplementasikan fungsi yang melakukan konjungsi logis . Dalam contoh berikut saya akan menggunakan yang siap dari sini :

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

Sayangnya, jika seseorang membutuhkan pesan khusus untuk setiap kasus yang gagal, maka, saya khawatir, tidak ada cara yang cukup fungsional. Atau, setidaknya, saya tidak dapat menemukannya.

13 cat Jan 31 2016 at 10:47

Jadi, saya bermain-main dengan sesuatu yang mirip dengan ini baru-baru ini, dan saya menemukan solusi berikut, yang menggunakan cara mendapatkan masukan yang menolak sampah, bahkan sebelum diperiksa dengan cara yang logis.

read_single_keypress()kesopanan 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()

Anda dapat menemukan modul lengkapnya di sini .

Contoh:

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

Perhatikan bahwa sifat dari implementasi ini adalah menutup stdin segera setelah sesuatu yang bukan berupa digit dibaca. Saya tidak menekan enter setelahnya a, tetapi saya perlu setelah angka.

Anda dapat menggabungkan ini dengan thismany()fungsi dalam modul yang sama untuk hanya mengizinkan, katakanlah, tiga digit.

12 Georgy May 11 2019 at 03:17

Menggunakan Click :

Click adalah pustaka untuk antarmuka baris perintah dan menyediakan fungsionalitas untuk meminta respons yang valid dari pengguna.

Contoh sederhana:

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

Perhatikan bagaimana itu mengubah nilai string menjadi float secara otomatis.

Memeriksa apakah suatu nilai berada dalam kisaran:

Ada berbagai jenis kustom yang disediakan. Untuk mendapatkan nomor dalam kisaran tertentu kita dapat menggunakan 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

Kami juga dapat menentukan salah satu batasannya, minatau 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

Pengujian keanggotaan:

Menggunakan click.Choicetipe. Secara default, pemeriksaan ini peka huruf besar / kecil.

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

Bekerja dengan jalur dan file:

Dengan menggunakan click.Pathtipe kita dapat memeriksa jalur yang ada dan juga mengatasinya:

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

Membaca dan menulis file dapat dilakukan dengan 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!

Contoh lain:

Konfirmasi kata kunci:

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

Nilai dasar:

Dalam hal ini, cukup menekan Enter(atau tombol apa pun yang Anda gunakan) tanpa memasukkan nilai, akan memberi Anda nilai default:

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 ojasmohril Jun 23 2016 at 17: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ãoManuelRodrigues Nov 28 2018 at 21:52

Berdasarkan saran yang sangat baik dari Daniel Q dan Patrick Artner, berikut ini adalah solusi yang lebih umum.

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

Saya memilih pernyataan eksplisit ifdan raisebukan assert, karena pemeriksaan pernyataan dapat dimatikan, sedangkan validasi harus selalu aktif untuk memberikan ketahanan.

Ini dapat digunakan untuk mendapatkan jenis masukan yang berbeda, dengan kondisi validasi yang berbeda. Sebagai contoh:

# 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!"})

Atau, untuk menjawab pertanyaan awal:

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 PratikAnand Apr 30 2017 at 16:29

Coba yang ini:-

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')
1 np8 Oct 30 2020 at 14:12

Ya, saya terlambat 6 tahun dari 🎉 tapi pertanyaan ini membutuhkan jawaban yang lebih terkini.

Pemisahan kekhawatiran

Saya adalah penggemar berat filosofi Unix "Lakukan satu hal dan lakukan dengan baik" . Dalam jenis masalah ini, praktik yang lebih baik adalah membagi masalah tersebut

  • Minta masukan get_inputsampai masukannya ok.
  • Validasi dalam validatorfungsi. Anda dapat menulis validator yang berbeda untuk kueri masukan yang berbeda.

Meminta masukan

Itu dapat dibuat sesederhana (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)

Contoh

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'

Python 3.8+ Catatan

Di Python 3.8+ Anda bisa menggunakan operator walrus

def get_input(prompt, validator, on_validationerror):
    while not validator(value := input(prompt)):
        print(on_validationerror)
    return value 
2Cubed May 31 2016 at 03:47

Meskipun blok try/ exceptakan berfungsi, cara yang jauh lebih cepat dan lebih bersih untuk menyelesaikan tugas ini adalah dengan menggunakan 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.")
SiddharthSatpathy Dec 18 2018 at 13:17

Pertanyaan bagus! Anda dapat mencoba kode berikut untuk ini. =)

Kode ini menggunakan ast.literal_eval () untuk menemukan tipe data dari input ( age). Kemudian mengikuti algoritma berikut:

  1. Minta pengguna untuk memasukkannya age.

    1.1. Jika ageadalah floatatau inttipe data:

    • Periksa apakah age>=18. Jika age>=18, cetak keluaran yang sesuai dan keluar.

    • Periksa apakah 0<age<18. Jika 0<age<18, cetak keluaran yang sesuai dan keluar.

    • Jika age<=0, minta pengguna untuk memasukkan nomor yang valid untuk usia lagi, ( yaitu kembali ke langkah 1.)

    1.2. Jika agebukan floatatau inttipe data, maka minta pengguna untuk memasukkan usianya lagi ( yaitu kembali ke langkah 1.)

Ini kodenya.

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.") 
Ep1c1aN Jul 01 2019 at 16:36

Anda selalu dapat menerapkan logika if-else sederhana dan menambahkan satu iflogika lagi ke kode Anda bersama dengan sebuah forloop.

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

Ini akan menjadi toilet yang tak terbatas dan Anda akan diminta untuk memasuki usia, tanpa batas.

Liju Aug 17 2020 at 15:24

Kode di bawah ini dapat membantu.

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='')

Jika Anda ingin mencoba maksimal, katakan 3, gunakan kode di bawah ini

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='')

Catatan: Ini menggunakan rekursi.

behnaz.sheikhi Sep 09 2020 at 19:30

Gunakan coba-kecuali untuk menangani kesalahan dan ulangi lagi:

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