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ệ
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ị -1
hợp lệ int
nhưng vô nghĩa trong bối cảnh này?
Trả lời
Cách đơn giản nhất để thực hiện điều này là đặt input
phương thức trong một vòng lặp while. Sử dụng continue
khi bạn nhận được thông tin đầu vào không tốt và break
ra 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 try
vàexcept
để 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 input
câ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 True
phươ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 input
thành raw_input
, nhưng vô tình chỉ thay đổi input
ở trên? Nó SyntaxError
chỉ đ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!
Tại sao bạn lại thực hiện một while True
và 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
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.
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?
-
Sự kết hợp nàyprompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
itertools.chain
vàitertools.repeat
sẽ 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
replies = map(input, prompts)
- ở đâymap
sẽ áp dụng tất cả cácprompts
chuỗi từ bước trước choinput
hà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...
- Chúng tôi sử dụng
filter
vàstr.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)
Và để chỉ lấy chuỗi chỉ có chữ số đầu tiên, chúng tôi sử dụngEnter a number: a Not a number! Try again: 1 1 Not a number! Try again: 2 2 Not a number! Try again: b Not a number! Try again: # and so on...
next
.
Các quy tắc xác thực khác:
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.isalpha
chỉ lấy chuỗi chữ cái hoặcstr.isupper
chỉ lấy chữ hoa. Xem tài liệu để biết danh sách đầy đủ.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
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ừ
operator
mô-đun.Sự tồn tại của đường dẫn:
Ở đây người ta có thể sử dụngpathlib
thư viện vàPath.exists
phươ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 next
hà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.lower
và str.strip
cá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.
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ố.
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 min
hoặ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.Choice
loạ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.Path
loạ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
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."
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 if
và raise
tuyê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.")
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')
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_input
cho đến khi đầu vào là ok. - Xác thực trong
validator
chứ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
Mặc dù a try
/ except
block 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.")
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:
Yêu cầu người dùng nhập cô ấy / anh ấy
age
.1.1. Nếu
age
làfloat
hoặcint
kiểu dữ liệu:
Kiểm tra xem
age>=18
. Nếuage>=18
, in đầu ra thích hợp và thoát.Kiểm tra xem
0<age<18
. Nếu0<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
age
không phảifloat
hoặcint
kiể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.")
Bạn luôn có thể áp dụng logic if-else đơn giản và thêm một if
logic nữa vào mã của mình cùng với một for
vò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.
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.
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")