Yêu cầu người dùng nhập liệu cho đến khi họ đưa ra phản hồi hợp lệ

Apr 25 2014

Tôi đang viết một chương trình chấp nhận đầu vào từ người dùng.

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

Chương trình hoạt động như mong đợi miễn là người dùng nhập dữ liệu có ý nghĩa.

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

Nhưng nó không thành công nếu người dùng nhập dữ liệu không hợp lệ:

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'

Thay vì gặp sự cố, tôi muốn chương trình yêu cầu nhập lại. Như thế này:

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!

Làm cách nào tôi có thể yêu cầu chương trình nhập các đầu vào hợp lệ thay vì bị treo khi nhập dữ liệu không hợp lý?

Làm cách nào để tôi có thể từ chối các giá trị như giá trị -1hợp lệ intnhưng vô nghĩa trong bối cảnh này?

Trả lời

776 Kevin Apr 25 2014 at 20:31

Cách đơn giản nhất để thực hiện điều này là đặt inputphương thức trong một vòng lặp while. Sử dụng continuekhi bạn nhận được thông tin đầu vào không tốt và breakra khỏi vòng lặp khi bạn hài lòng.

Khi đầu vào của bạn có thể tăng ngoại lệ

Sử dụng tryexcept để phát hiện khi người dùng nhập dữ liệu không thể phân tích cú pháp.

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

Triển khai các quy tắc xác thực của riêng bạn

Nếu bạn muốn từ chối các giá trị mà Python có thể phân tích cú pháp thành công, bạn có thể thêm logic xác thực của riêng mình.

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

Kết hợp Xử lý Ngoại lệ và Xác thực Tùy chỉnh

Cả hai kỹ thuật trên có thể được kết hợp thành một vòng lặp.

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

Đóng gói tất cả trong một hàm

Nếu bạn cần yêu cầu người dùng của mình cung cấp nhiều giá trị khác nhau, có thể hữu ích khi đặt mã này vào một hàm để bạn không phải nhập lại mã mỗi lần.

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

Để tất cả chúng cùng nhau

Bạn có thể mở rộng ý tưởng này để tạo một hàm đầu vào rất chung chung:

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

Với cách sử dụng như:

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

Những cạm bẫy phổ biến và tại sao bạn nên tránh chúng

Việc sử dụng dự phòng của các inputcâu lệnh dự phòng

Phương pháp này hoạt động nhưng thường được coi là kiểu kém:

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

Ban đầu, nó có vẻ hấp dẫn vì nó ngắn hơn while Truephương pháp, nhưng nó vi phạm nguyên tắc Không lặp lại bản thân trong phát triển phần mềm. Điều này làm tăng khả năng xuất hiện lỗi trong hệ thống của bạn. Điều gì sẽ xảy ra nếu bạn muốn backport thành 2.7 bằng cách thay đổi inputthành raw_input, nhưng vô tình chỉ thay đổi inputở trên? Nó SyntaxErrorchỉ đang chờ đợi để xảy ra.

Đệ quy sẽ thổi bay ngăn xếp của bạn

Nếu bạn vừa mới học về đệ quy, bạn có thể muốn sử dụng nó get_non_negative_intđể có thể loại bỏ vòng lặp 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

Điều này dường như hoạt động tốt trong hầu hết thời gian, nhưng nếu người dùng nhập dữ liệu không hợp lệ đủ lần, tập lệnh sẽ kết thúc bằng a RuntimeError: maximum recursion depth exceeded. Bạn có thể nghĩ rằng "không có kẻ ngốc nào phạm 1000 lỗi liên tiếp", nhưng bạn đang đánh giá thấp sự khéo léo của những kẻ ngu ngốc!

46 StevenStip Jan 14 2016 at 19:43

Tại sao bạn lại thực hiện một while Truevà sau đó thoát ra khỏi vòng lặp này trong khi bạn cũng có thể chỉ cần đưa các yêu cầu của mình vào câu lệnh while vì tất cả những gì bạn muốn là dừng lại khi đã đủ tuổi?

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

Điều này sẽ dẫn đến những điều sau:

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.

điều này sẽ hoạt động vì tuổi tác sẽ không bao giờ có giá trị không có ý nghĩa và mã tuân theo logic của "quy trình kinh doanh" của bạn

26 aaveg Jun 29 2015 at 06:29

Mặc dù câu trả lời được chấp nhận là tuyệt vời. Tôi cũng muốn chia sẻ một cách hack nhanh chóng cho vấn đề này. (Điều này cũng giải quyết vấn đề tuổi tác tiêu cực.)

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 Mã này dành cho python 3.x.

17 Georgy May 10 2019 at 23:47

Phương pháp tiếp cận chức năng hoặc " nhìn mẹ không có vòng lặp! ":

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

hoặc nếu bạn muốn tách thông báo "đầu vào không hợp lệ" khỏi lời nhắc nhập như trong các câu trả lời khác:

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

Làm thế nào nó hoạt động?

  1. prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
    
    Sự kết hợp này itertools.chainitertools.repeatsẽ tạo ra một trình lặp sẽ mang lại chuỗi "Enter a number: "một lần và "Not a number! Try again: "số lần vô hạn:
    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)- ở đây mapsẽ áp dụng tất cả các promptschuỗi từ bước trước cho inputhàm. Ví dụ:
    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. Chúng tôi sử dụng filterstr.isdigitđể lọc ra những chuỗi chỉ chứa các chữ số:
    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...
    
    Và để chỉ lấy chuỗi chỉ có chữ số đầu tiên, chúng tôi sử dụng next.

Các quy tắc xác thực khác:

  1. Phương thức chuỗi: Tất nhiên bạn có thể sử dụng các phương thức chuỗi khác như str.isalphachỉ lấy chuỗi chữ cái hoặc str.isupperchỉ lấy chữ hoa. Xem tài liệu để biết danh sách đầy đủ.

  2. Kiểm tra tư cách thành viên:
    Có một số cách khác nhau để thực hiện. Một trong số đó là sử dụng __contains__phương pháp:

    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. So sánh số:
    Có những phương pháp so sánh hữu ích mà chúng ta có thể sử dụng ở đây. Ví dụ, cho __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
    

    Hoặc, nếu bạn không thích sử dụng các phương thức dunder (dunder = double-underscore), bạn luôn có thể xác định hàm của riêng mình hoặc sử dụng các hàm từ operatormô-đun.

  4. Sự tồn tại của đường dẫn:
    Ở đây người ta có thể sử dụng pathlibthư viện và Path.existsphương thức của nó :

    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
    

Giới hạn số lần thử:

Nếu bạn không muốn tra tấn người dùng bằng cách hỏi anh ta điều gì đó vô số lần, bạn có thể chỉ định giới hạn trong một lệnh gọi itertools.repeat. Điều này có thể được kết hợp với việc cung cấp giá trị mặc định cho nexthàm:

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!

Xử lý trước dữ liệu đầu vào:

Đôi khi chúng tôi không muốn từ chối một đầu vào nếu người dùng vô tình cung cấp nó IN HOA hoặc có khoảng trắng ở đầu hoặc cuối chuỗi. Để tính đến những sai lầm đơn giản này, chúng ta có thể xử lý trước dữ liệu đầu vào bằng cách áp dụng str.lowerstr.stripcác phương pháp. Ví dụ: đối với trường hợp kiểm tra tư cách thành viên, mã sẽ như thế này:

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

Trong trường hợp bạn có nhiều hàm cần sử dụng để tiền xử lý, thì việc sử dụng một hàm thực hiện một thành phần hàm có thể dễ dàng hơn . Ví dụ: sử dụng một từ đây :

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

Kết hợp các quy tắc xác thực:

Đối với một trường hợp đơn giản, chẳng hạn, khi chương trình yêu cầu độ tuổi từ 1 đến 120, người ta có thể thêm một người khác 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)

Nhưng trong trường hợp có nhiều quy tắc, tốt hơn nên triển khai một hàm thực hiện kết hợp logic . Trong ví dụ sau, tôi sẽ sử dụng một cái sẵn sàng từ đây :

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

Thật không may, nếu ai đó cần có một thông báo tùy chỉnh cho từng trường hợp thất bại, sau đó, tôi sợ, không có khá cách chức năng. Hoặc, ít nhất, tôi không thể tìm thấy một.

13 cat Jan 31 2016 at 10:47

Vì vậy, gần đây tôi đã làm lộn xộn với một thứ tương tự như thế này, và tôi đã đưa ra giải pháp sau, sử dụng một cách nhận đầu vào để loại bỏ rác, trước khi nó được kiểm tra theo bất kỳ cách hợp lý nào.

read_single_keypress()lịch sự 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()

Bạn có thể tìm thấy mô-đun hoàn chỉnh ở đây .

Thí dụ:

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

Lưu ý rằng bản chất của việc triển khai này là nó đóng stdin ngay sau khi một thứ gì đó không phải là chữ số được đọc. Tôi không nhấn enter sau a, nhưng tôi cần nhấn sau các con số.

Bạn có thể hợp nhất hàm này với thismany()hàm trong cùng một mô-đun để chỉ cho phép, chẳng hạn, ba chữ số.

12 Georgy May 11 2019 at 03:17

Sử dụng Nhấp chuột :

Click là một thư viện cho các giao diện dòng lệnh và nó cung cấp chức năng để yêu cầu phản hồi hợp lệ từ người dùng.

Ví dụ đơn giản:

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

Lưu ý cách nó tự động chuyển đổi giá trị chuỗi thành một số nổi.

Kiểm tra xem giá trị có nằm trong phạm vi không:

Có các loại tùy chỉnh khác nhau được cung cấp. Để nhận một số trong một phạm vi cụ thể, chúng ta có thể sử dụng 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

Chúng tôi cũng có thể chỉ định một trong các giới hạn minhoặc 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

Kiểm tra tư cách thành viên:

Đang sử dụng click.Choiceloại. Theo mặc định, kiểm tra này phân biệt chữ hoa chữ thường.

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

Làm việc với các đường dẫn và tệp:

Sử dụng một click.Pathloại, chúng tôi có thể kiểm tra các đường dẫn hiện có và cũng giải quyết chúng:

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

Việc đọc và ghi tệp có thể được thực hiện bằng cách 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!

Những ví dụ khác:

Xác nhận mật khẩu:

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

Giá trị mặc định:

Trong trường hợp này, chỉ cần nhấn Enter(hoặc bất kỳ phím nào bạn sử dụng) mà không nhập giá trị, sẽ cung cấp cho bạn giá trị mặc định:

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

Dựa trên các đề xuất tuyệt vời của Daniel Q và Patrick Artner, đây là một giải pháp tổng quát hơn.

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

Tôi đã chọn rõ ràng ifraisetuyên bố thay vì một assert, vì kiểm tra xác nhận có thể bị tắt, trong khi xác thực phải luôn được bật để cung cấp tính mạnh mẽ.

Điều này có thể được sử dụng để nhận các loại đầu vào khác nhau, với các điều kiện xác nhận khác nhau. Ví dụ:

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

Hoặc, để trả lời câu hỏi ban đầu:

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

Hãy thử cái này: -

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

Vâng, tôi đã trễ 6 năm kể từ ngày 🎉 nhưng câu hỏi này xứng đáng có câu trả lời cập nhật hơn.

Tách mối quan tâm

Tôi là một fan hâm mộ lớn của triết lý Unix "Làm một việc và làm tốt" . Trong loại vấn đề này, cách tốt hơn là chia vấn đề thành

  • Yêu cầu đầu vào get_inputcho đến khi đầu vào là ok.
  • Xác thực trong validatorchức năng. Bạn có thể viết các trình xác thực khác nhau cho các truy vấn đầu vào khác nhau.

Yêu cầu đầu vào

Nó có thể được giữ đơn giản như (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)

Thí dụ

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'

Lưu ý Python 3.8+

Trong Python 3.8+, bạn có thể sử dụng toán tử hải mã

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

Mặc dù a try/ exceptblock sẽ hoạt động, nhưng cách nhanh hơn và rõ ràng hơn để hoàn thành tác vụ này là sử dụng 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

Câu hỏi hay! Bạn có thể thử mã sau cho điều này. =)

Mã này sử dụng ast.literal_eval () để tìm kiểu dữ liệu của đầu vào ( age). Sau đó, nó tuân theo thuật toán sau:

  1. Yêu cầu người dùng nhập cô ấy / anh ấy age.

    1.1. Nếu agefloathoặc intkiểu dữ liệu:

    • Kiểm tra xem age>=18. Nếu age>=18, in đầu ra thích hợp và thoát.

    • Kiểm tra xem 0<age<18. Nếu 0<age<18, in đầu ra thích hợp và thoát.

    • Nếu age<=0, hãy yêu cầu người dùng nhập lại một số hợp lệ cho độ tuổi, ( tức là quay lại bước 1)

    1.2. Nếu agekhông phải floathoặc intkiểu dữ liệu, hãy yêu cầu người dùng nhập lại tuổi của cô ấy / anh ấy ( tức là quay lại bước 1)

Đây là mã.

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

Bạn luôn có thể áp dụng logic if-else đơn giản và thêm một iflogic nữa vào mã của mình cùng với một forvòng lặp.

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

Đây sẽ là khoảng thời gian vô hạn và bạn sẽ được yêu cầu nhập độ tuổi vô thời hạn.

Liju Aug 17 2020 at 15:24

Mã dưới đây có thể hữu ích.

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

Nếu bạn muốn có số lần thử tối đa, hãy nói 3, sử dụng mã bên dưới

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

Lưu ý: Điều này sử dụng đệ quy.

behnaz.sheikhi Sep 09 2020 at 19:30

Sử dụng thử ngoại trừ để xử lý lỗi và lặp lại lỗi:

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