Ich schreibe ein Programm, das Eingaben des Benutzers akzeptieren muss.
#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.")
Dies funktioniert erwartungsgemäß, wenn der Benutzer sensible Daten eingibt.
C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!
Wenn sie jedoch einen Fehler machen, stürzt sie ab:
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'
Anstelle eines Absturzes möchte ich, dass die Eingabe erneut versucht wird. So was:
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!
Wie kann ich das erreichen? Was ist, wenn ich auch Werte wie -1
, die eine gültige int
sind, ablehnen möchten, in diesem Zusammenhang jedoch unsinnig?
Der einfachste Weg, dies zu erreichen, wäre, die input
-Methode in eine while-Schleife zu setzen. Verwenden Sie continue
, wenn Sie eine schlechte Eingabe erhalten, und break
außerhalb der Schleife, wenn Sie zufrieden sind.
Verwenden Sie try and catch , um festzustellen, wann der Benutzer Daten eingibt, die nicht analysiert werden können.
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.")
Wenn Sie Werte ablehnen möchten, die Python erfolgreich parsen kann, können Sie Ihre eigene Validierungslogik hinzufügen.
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
Beide der obigen Techniken können in einer Schleife kombiniert werden.
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.")
Wenn Sie Ihren Benutzer nach vielen verschiedenen Werten fragen müssen, kann es nützlich sein, diesen Code in eine Funktion zu schreiben, damit Sie ihn nicht jedes Mal erneut eingeben müssen.
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: ")
Sie können diese Idee erweitern, um eine sehr generische Eingabefunktion zu erstellen:
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:
print(template.format(" or ".join((", ".join(map(str,
range_[:-1])),
str(range_[-1])))))
else:
return ui
Bei Verwendung wie:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
input
-AnweisungenDiese Methode funktioniert, wird aber allgemein als schlechter Stil angesehen:
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): ")
Es mag anfangs attraktiv aussehen, weil es kürzer ist als die while True
-Methode, aber es verstößt gegen das Don't Repeat Yourself Prinzip der Softwareentwicklung. Dies erhöht die Wahrscheinlichkeit von Fehlern in Ihrem System. Was ist, wenn Sie auf 2.7 zurückportieren möchten, indem Sie input
in raw_input
ändern, aber versehentlich nur das erste input
oben ändern? Es ist eine SyntaxError
, die nur darauf wartet zu geschehen.
Wenn Sie gerade etwas über Rekursion gelernt haben, könnten Sie versucht sein, sie in get_non_negative_int
zu verwenden, um die while-Schleife zu beseitigen.
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
Dies scheint in der Regel gut zu funktionieren. Wenn der Benutzer jedoch mehrmals ungültige Daten eingibt, wird das Skript mit einem RuntimeError: maximum recursion depth exceeded
beendet. Sie denken vielleicht "kein Dummkopf würde 1000 Fehler hintereinander machen", aber Sie unterschätzen den Einfallsreichtum der Dummköpfe!
Warum sollten Sie einen while True
ausführen und dann aus dieser Schleife ausbrechen, während Sie Ihre Anforderungen auch einfach in die while-Anweisung einfügen können, da Sie nur dann aufhören möchten, wenn Sie das Alter haben?
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.")
Dies würde folgendes ergeben:
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.
dies wird funktionieren, da das Alter niemals einen Wert haben wird, der keinen Sinn ergibt, und der Code folgt der Logik Ihres "Geschäftsprozesses".
Obwohl die akzeptierte Antwort erstaunlich ist. Ich würde auch gerne einen schnellen Hack für dieses Problem geben. (Dies kümmert sich auch um das negative Alterproblem.)
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: ")))
P.S. Dieser Code ist für Python 3.x.
Also habe ich vor kurzem mit etwas Ähnlichem rumgespielt, und ich habe die folgende Lösung gefunden, die eine Art der Eingabe von Junk verwendet, bevor sie überhaupt auf logische Weise geprüft wird.
read_single_keypress()
Courtesy 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()
Das komplette Modul finden Sie hier .
Beispiel:
$ ./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!
$ _
Beachten Sie, dass die Implementierung von stdin abgeschlossen ist, sobald etwas gelesen wird, das keine Ziffer ist. Ich drückte nach a
nicht auf die Eingabetaste, musste aber nach den Zahlen suchen.
Sie könnten dies mit der Funktion thismany()
im selben Modul zusammenführen, um beispielsweise nur drei Ziffern zuzulassen.
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."
So bearbeiten Sie Ihren Code und beheben den Fehler:
while True:
try:
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
break
else:
print("You are not able to vote in the United States.")
break
except ValueError:
print("Please enter a valid response")
Probier diese:-
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')
Verwenden Sie die "while" -Anweisung, bis der Benutzer einen wahren Wert eingibt. Wenn der Eingabewert keine Zahl ist oder ein Nullwert ist, überspringen Sie ihn und versuchen Sie, erneut zu fragen usw. In meinem Beispiel habe ich versucht, Ihre Frage wirklich zu beantworten. Wenn wir annehmen, dass unser Alter zwischen 1 und 150 liegt, wird der Eingabewert akzeptiert, ansonsten ist es ein falscher Wert. Zum Beenden des Programms kann der Benutzer die 0-Taste verwenden und als Wert eingeben.
Hinweis: Lesen Sie die Kommentare oben im Code.
# If your input value is only a number then use "Value.isdigit() == False".
# If you need an input that is a text, you should remove "Value.isdigit() == False".
def Input(Message):
Value = None
while Value == None or Value.isdigit() == False:
try:
Value = str(input(Message)).strip()
except InputError:
Value = None
return Value
# Example:
age = 0
# If we suppose that our age is between 1 and 150 then input value accepted,
# else it's a wrong value.
while age <=0 or age >150:
age = int(Input("Please enter your age: "))
# For terminating program, the user can use 0 key and enter it as an a value.
if age == 0:
print("Terminating ...")
exit(0)
if age >= 18 and age <=150:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Click ist eine Bibliothek für Befehlszeilenschnittstellen und bietet Funktionen zum Abfragen einer gültigen Antwort von einem Benutzer.
Einfaches Beispiel:
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
Beachten Sie, wie der Zeichenfolgenwert automatisch in einen Gleitkommawert konvertiert wird.
Es gibt verschiedene benutzerdefinierte Typen zur Verfügung gestellt. Um eine Nummer in einem bestimmten Bereich zu erhalten, können wir IntRange
verwenden:
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
Wir können auch nur einen der Grenzwerte min
oder max
angeben:
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
Verwenden Sie den Typ click.Choice
. Bei dieser Prüfung wird standardmäßig zwischen Groß- und Kleinschreibung unterschieden.
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
Mit einem click.Path
-Typ können wir nach vorhandenen Pfaden suchen und diese auch auflösen:
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
Das Lesen und Schreiben von Dateien kann mit click.File
erfolgen:
file = click.Prompt('In which file to write data?', type=click.File('w'))
with file.open():
file.write('Hello!')
# More info about `lazy=True` at:
# https://click.palletsprojects.com/en/7.x/arguments/#file-opening-safety
file = click.Prompt('Which file you wanna read?', type=click.File(lazy=True))
with file.open():
print(file.read())
In which file to write data?:
# <-- provided an empty string, which is an illegal name for a file
In which file to write data?:
some_file.txt
Which file you wanna read?:
nonexistent.txt
Error: Could not open file: nonexistent.txt: No such file or directory
Which file you wanna read?:
some_file.txt
Hello!
password = click.Prompt('Enter password', hide_input=True, confirmation_Prompt=True)
print(password)
Enter password:
······
Repeat for confirmation:
·
Error: the two entered values do not match
Enter password:
······
Repeat for confirmation:
······
qwerty
In diesem Fall einfach drücken Enter Wenn Sie keinen Wert eingeben, erhalten Sie einen Standardwert:
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
Sie können eine allgemeinere Logik schreiben, damit der Benutzer nur eine bestimmte Anzahl von Malen eingeben kann, da derselbe Anwendungsfall in vielen realen Anwendungen auftritt.
def getValidInt(iMaxAttemps = None):
iCount = 0
while True:
# exit when maximum attempt limit has expired
if iCount != None and iCount > iMaxAttemps:
return 0 # return as default value
i = raw_input("Enter no")
try:
i = int(i)
except ValueError as e:
print "Enter valid int value"
else:
break
return i
age = getValidInt()
# do whatever you want to do.
Aufbauend auf den hervorragenden Vorschlägen von Daniel Q und Patrick Artner, gibt es hier eine noch allgemeinere Lösung.
# 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)
Ich entschied mich für explizite if
- und raise
-Anweisungen anstelle von assert
, Weil die Assertionsprüfung deaktiviert ist, Während die Validierung immer eingeschaltet sein sollte, um Robustheit zu gewährleisten.
Dies kann verwendet werden, um verschiedene Arten von Eingaben abzurufen, Mit unterschiedlichen Validierungsbedingungen . Zum Beispiel:
# 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!"})
Oder um die ursprüngliche Frage zu beantworten:
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.")
Gute Frage! Sie können den folgenden Code dafür ausprobieren. =)
Dieser Code verwendet ast.literal_eval () , um den Datentyp der Eingabe (age
) zu finden. Dann folgt folgender Algorithmus:
Bitten Sie den Benutzer, seine/seine
age
einzugeben.1.1. Wenn
age
der Datentypfloat
oderint
ist:
Prüfen Sie, ob
age>=18
. Wennage>=18
, die entsprechende Ausgabe drucken und beenden.Prüfen Sie, ob
0<age<18
. Wenn0<age<18
, die entsprechende Ausgabe drucken und beenden.Wenn
age<=0
, bitten Sie den Benutzer, erneut eine gültige Zahl für das Alter einzugeben, (d. H. Gehen Sie zu Schritt 1 zurück.)1.2. Wenn
age
nicht der Datentypfloat
oderint
ist, bitten Sie den Benutzer, sein Alter erneut einzugeben (d. H. Gehe zu Schritt 1 zurück.)
Hier ist der Code.
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.")
Ein try
/except
-Block funktioniert zwar, eine sehr viel schnellere und sauberere Methode zum Ausführen dieser Aufgabe wäre jedoch die Verwendung von 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.")
Permanente Benutzereingabe mit rekursiver Funktion :
def askName():
return input("Write your name: ").strip() or askName()
name = askName()
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
und schließlich die Fragestellung:
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
responseAge = [
"You are able to vote in the United States!",
"You are not able to vote in the United States.",
][int(age < 18)]
print(responseAge)
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
oder wenn Sie möchten, dass eine "schlechte Eingabe" -Nachricht von einer Eingabeaufforderung wie in anderen Antworten getrennt wird:
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
prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
Diese Kombination aus itertools.chain
und itertools.repeat
erstellt einen Iterator, der Zeichenfolgen "Enter a number: "
einmal und "Not a number! Try again: "
unendlich oft ergibt: 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)
- here map
wendet alle Zeichenfolgen von prompts
aus dem vorherigen Schritt auf die Funktion input
an. Z.B.: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...
filter
und str.isdigit
, um die Zeichenfolgen herauszufiltern, die nur Ziffern enthalten: 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...
Und um nur den String mit den ersten Ziffern zu erhalten, verwenden wir next
. Zeichenkettenmethoden: Natürlich können Sie auch andere Zeichenkettenmethoden wie str.isalpha
verwenden, um nur alphabetische Zeichenketten abzurufen, oder str.isupper
, um nur Großbuchstaben abzurufen. Siehe docs für die vollständige Liste.
Mitgliedschaftstest:
Es gibt verschiedene Möglichkeiten, dies durchzuführen. Eine davon ist die Verwendung der Methode __contains__
:
from itertools import chain, repeat
fruits = {'Apple', 'orange', 'Peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
valid_response = next(filter(fruits.__contains__, replies))
print(valid_response)
Enter a fruit: 1
I don't know this one! Try again: foo
I don't know this one! Try again: Apple
apple
Zahlenvergleich:
Es gibt nützliche Vergleichsmethoden, die wir hier anwenden können. Zum Beispiel für __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
Wenn Ihnen das nicht gefällt, können Sie jederzeit Ihre eigene Funktion definieren oder die aus dem Modul operator
verwenden.
Pfadexistenz:
Hier kann man die pathlib
Bibliothek und ihre Path.exists
Methode verwenden:
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
Wenn Sie einen Benutzer nicht mit einer unendlichen Anzahl von Fragen foltern möchten, können Sie in einem Aufruf von itertools.repeat
ein Limit angeben. Dies kann mit der Bereitstellung eines Standardwerts für die Funktion next
kombiniert werden:
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!
Für einen einfachen Fall, zum Beispiel, wenn das Programm nach einem Alter zwischen 1 und 120 Jahren fragt, kann man einfach eine weitere filter
hinzufügen:
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)
Wenn es jedoch viele Regeln gibt, ist es besser, eine Funktion zu implementieren, die eine logische Verknüpfung ausführt. Im folgenden Beispiel verwende ich ein fertiges von hier :
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
Leider, wenn jemand eine benutzerdefinierte Nachricht für jeden fehlgeschlagenen Fall benötigt, dann gibt es leider keine hübschefunktionale Möglichkeit. Oder zumindest konnte ich keine finden.
Verwenden Sie try catch, ohne die Schleife zu beenden. Verwenden Sie die IF-Anweisung, um zu überprüfen, ob die Zeichenfolge leer ist.
while True:
name = input("Enter Your Name\n")
if not name:
print("I did not understood that")
continue
else:
break
while True:
try:
salary = float(input("whats ur salary\n"))
except ValueError:
print("I did not understood that")
continue
else:
break
while True:
try:
print("whats ur age?")
age = int(float(input()))
except ValueError:
print("I did not understood that")
continue
else:
break
print("Hello "+ name + "\nYour salary is " + str(salary) + '\nand you will be ' + str(age+1) +' in a Year')
Hier ist eine saubere, allgemeinere Lösung, die wiederholte if/else-Blöcke vermeidet: Schreiben Sie eine Funktion, die (Error, Error Prompt) -Paare in ein Wörterbuch einnimmt, und überprüfen Sie Ihre Werte mit Assertions.
def validate_input(Prompt, error_map):
while True:
try:
data = int(input(Prompt))
# Insert your non-exception-throwing conditionals here
assert data > 0
return data
# Print whatever text you want the user to see
# depending on how they messed up
except Tuple(error_map.keys()) as e:
print(error_map[type(e)])
Verwendungszweck:
d = {ValueError: 'Integers only', AssertionError: 'Positive numbers only',
KeyboardInterrupt: 'You can never leave'}
user_input = validate_input("Positive number: ", d)
Eine weitere Lösung für die Verwendung der Eingabevalidierung mithilfe einer benutzerdefinierten ValidationError
und einer (optionalen) Bereichsvalidierung für Ganzzahleneingaben
class ValidationError(ValueError):
"""Special validation error - its message is supposed to be printed"""
pass
def RangeValidator(text,num,r):
"""Generic validator - raises 'text' as ValidationError if 'num' not in range 'r'."""
if num in r:
return num
raise ValidationError(text)
def ValidCol(c):
"""Specialized column validator providing text and range."""
return RangeValidator("Columns must be in the range of 0 to 3 (inclusive)",
c, range(4))
def ValidRow(r):
"""Specialized row validator providing text and range."""
return RangeValidator("Rows must be in the range of 5 to 15(exclusive)",
r, range(5,15))
Verwendungszweck:
def GetInt(text, validator=None):
"""Aks user for integer input until a valid integer is given. If provided,
a 'validator' function takes the integer and either raises a
ValidationError to be printed or returns the valid number.
Non integers display a simple error message."""
print()
while True:
n = input(text)
try:
n = int(n)
return n if validator is None else validator(n)
except ValueError as ve:
# prints ValidationErrors directly - else generic message:
if isinstance(ve, ValidationError):
print(ve)
else:
print("Invalid input: ", n)
column = GetInt("Pleased enter column: ", ValidCol)
row = GetInt("Pleased enter row: ", ValidRow)
print( row, column)
Ausgabe:
Pleased enter column: 22
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: -2
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: 2
Pleased enter row: a
Invalid input: a
Pleased enter row: 72
Rows must be in the range of 5 to 15(exclusive)
Pleased enter row: 9
9, 2
Daraufhin wird der Benutzer aufgefordert, die Nummer einzugeben, bis er eine gültige Nummer eingegeben hat:
#note: Python 2.7 users should use raw_input, the equivalent of 3.X's input
while(1):
try:
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
break()
else:
print("You are not able to vote in the United States.")
break()
except:
print("Please only enter numbers ")
Sie können jederzeit eine einfache if-else-Logik anwenden und Ihrem Code eine weitere if
-Logik zusammen mit einer for
-Schleife hinzufügen.
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
Dies wird ein unendliches Klo sein und Sie werden gebeten, das Alter auf unbestimmte Zeit einzugeben.
Sie können für die Eingabeanweisung eine while-True-Schleife festlegen, sodass Sie wiederholt nach den Eingaben des Benutzers gefragt werden und diese Schleife dann unterbrechen, wenn der Benutzer die gewünschte Antwort eingibt. Sie können try- und except-Blöcke verwenden, um ungültige Antworten zu verarbeiten.
while True:
var = True
try:
age = int(input("Please enter your age: "))
except ValueError:
print("Invalid input.")
var = False
if var == True:
if age >= 18:
print("You are able to vote in the United States.")
break
else:
print("You are not able to vote in the United States.")
Die Variable var ist nur so, dass das Programm nicht zurückgibt, wenn der Benutzer eine Zeichenfolge anstelle einer Ganzzahl eingibt, "Sie können in den Vereinigten Staaten nicht abstimmen."