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ệ

609
Kevin 2014-04-26 03:31.

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?

15 answers

776
Kevin 2014-04-26 03: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
Steven Stip 2016-01-15 02: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 2015-06-29 13: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 2019-05-11 06: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 2016-01-31 17: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 2019-05-11 10: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
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.

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
Pratik Anand 2017-04-30 23: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('[[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.

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 
0
2Cubed 2016-05-31 10: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.")
0
Siddharth Satpathy 2018-12-18 20: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.") 
0
Ep1c1aN 2019-07-01 23: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.

0
Liju 2020-08-17 22: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.

0
behnaz.sheikhi 2020-09-10 02: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")

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

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!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Xem đoạn giới thiệu cho bộ phim chuyển thể đầy khói lửa, có sự góp mặt của ngôi sao Edward Norton từ phim Motherless Brooklyn của Jonathan Lethem

Xem đoạn giới thiệu cho bộ phim chuyển thể đầy khói lửa, có sự góp mặt của ngôi sao Edward Norton từ phim Motherless Brooklyn của Jonathan Lethem

Edward Norton đã muốn đưa cuốn tiểu thuyết Motherless Brooklyn của Jonathan Lethem's Joycean 1999 lên màn ảnh kể từ khi nó được xuất bản. Bây giờ, 20 năm sau, một đoạn giới thiệu đã xuất hiện cho câu chuyện sôi nổi, đưa câu chuyện của Lethem trở lại những năm 1950 với rất nhiều gương mặt quen thuộc.

Cách dễ dàng chọn không tham gia trọng tài ràng buộc thẻ Apple

Cách dễ dàng chọn không tham gia trọng tài ràng buộc thẻ Apple

Có thích thú khi sử dụng Thẻ Apple mới của bạn không? Trước khi bạn bắt đầu chi tiêu, có một nhiệm vụ bổ sung cần xem xét: chọn không tham gia trọng tài ràng buộc. Bạn sẽ phát hiện ra các điều khoản trọng tài ràng buộc trong nhiều thỏa thuận tài chính vì nó giúp ngăn các ngân hàng và đối tác kinh doanh của họ không phải ra tòa.

Những người chơi Fortnite World Cup không ghi bàn có cảm giác hài hước về điều đó

Những người chơi Fortnite World Cup không ghi bàn có cảm giác hài hước về điều đó

Điểm số tại vòng chung kết Fortnite World Cup Solo hôm nay là rất lớn, với người chiến thắng Bugha ghi được nhiều hơn 26 điểm so với người về thứ hai là Psalm. Nhưng không phải ai cũng có thể giành chiến thắng: Bốn cầu thủ ra về với 0 điểm, nhưng — ít nhất là trên Twitter — họ là những người thể thao tốt về điều đó.

Báo cáo: Cánh cửa tuyển sinh có thể đã mở cho các ứng viên UCLA có mối quan hệ có ảnh hưởng

Báo cáo: Cánh cửa tuyển sinh có thể đã mở cho các ứng viên UCLA có mối quan hệ có ảnh hưởng

Huấn luyện viên trưởng của bộ môn thể dục dụng cụ UCLA Valorie Kondos-Field theo dõi Katelyn Ohashi thi đấu thăng bằng trong trận gặp Stanford tại Pauley Pavilion vào ngày 10 tháng 3 năm 2019 ở Los Angeles, California. Vụ bê bối gian lận tuyển sinh đại học tiết lộ các chi tiết của một quá trình chính thức hóa để đưa những đứa trẻ thất bại của các gia đình giàu có và nổi tiếng vào các trường đại học đáng tin cậy và danh tiếng, sử dụng một "cửa phụ" đắt tiền cho các bậc cha mẹ mà sự giàu có của họ khiến họ không có cơ hội. chỉ cần tài trợ cho một cánh mới trong khuôn viên trường.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Lưu ý của người biên tập: Bạn đang xem tài liệu lỗi thời từ blog DFINITY đang được bảo quản cho mục đích lưu trữ.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Bài đăng này khám phá tầm nhìn về đám mây phi tập trung của nhóm DFINITY và cách nó liên quan đến các nhà cung cấp blockchain truyền thống và đám mây hiện có như Amazon Web Services. Các minh chứng về công nghệ DFINITY được áp dụng bởi một mạng lưới quy mô lớn sẽ được thực hiện vào mùa thu năm 2017, sau đó sẽ được gây quỹ Chính cho quỹ hỗ trợ phi lợi nhuận, với mạng “đám mây mở” dự kiến ​​sẽ ra mắt vào đầu mùa hè năm 2018 .

Language