Ik schrijf een programma dat invoer van de gebruiker accepteert.
#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.")
Het programma werkt zoals verwacht zolang de gebruiker zinvolle gegevens invoert.
C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!
Maar het mislukt als de gebruiker ongeldige gegevens invoert:
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'
In plaats van te crashen, wil ik dat het programma opnieuw om invoer vraagt. Zoals dit:
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!
Hoe kan ik ervoor zorgen dat het programma om geldige invoer vraagt in plaats van te crashen wanneer onzinnige gegevens worden ingevoerd?
Hoe kan ik waarden zoals -1
weigeren, wat een geldige int
is, maar onzinnig in deze context?
Antwoord 1, autoriteit 100%
De eenvoudigste manier om dit te bereiken is het input
methode even loop gezet. Gebruik continue
als je slechte input, en break
uit de lus als je tevreden bent.
When Your Input opwerpt een uitzondering
Met try
en except
detecteren wanneer de gebruikersgegevens die niet kunnen worden ontleed binnenkomt.
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.")
Het implementeren van uw eigen Validatieregels
Als u wilt waarden verwerpen die Python succes kan ontleden, kunt u uw eigen validatie logica toe te voegen.
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
Combinatie van uitzonderingsafhandeling en aangepaste validatie
Beide bovengenoemde technieken kunnen in één lus worden gecombineerd.
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.")
Inkapselt het allemaal in een functie
Als u uw gebruiker voor veel verschillende waarden moet stellen, kan het nuttig zijn om deze code in een functie te plaatsen, zodat u deze niet telkens hoeft te typen.
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: ")
alles samenstellen
U kunt dit idee uitbreiden om een zeer generieke invoerfunctie te maken:
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
Bij gebruik zoals:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
Veelvoorkomende valkuilen en waarom je ze moet vermijden
Het redundante gebruik van redundante input
-statements
Deze methode werkt, maar wordt over het algemeen als een slechte stijl beschouwd:
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): ")
Het ziet er in eerste instantie misschien aantrekkelijk uit omdat het korter is dan de while True
methode, maar het schendt de Herhaal jezelf nietprincipe van softwareontwikkeling. Dit vergroot de kans op bugs in uw systeem. Wat als je wilt backporten naar 2.7 door input
te veranderen in raw_input
, maar per ongeluk alleen de eerste input
hierboven wijzigt? Het is een SyntaxError
die wacht om te gebeuren.
Recursie zal je stapel opblazen
Als je net hebt geleerd over recursie, kom je misschien in de verleiding om het in get_non_negative_int
te gebruiken, zodat je de while-lus kunt weggooien.
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
Dit lijkt meestal goed te werken, maar als de gebruiker vaak genoeg ongeldige gegevens invoert, wordt het script beëindigd met een RuntimeError: maximum recursion depth exceeded
. Je denkt misschien “geen dwaas zou 1000 fouten achter elkaar maken”, maar je onderschat de vindingrijkheid van dwazen!
Antwoord 2, autoriteit 6%
Waarom zou je een while True
doen en dan uit deze lus breken, terwijl je ook gewoon je eisen in de while-statement kunt zetten, aangezien je alleen maar wilt stoppen als je de leeftijd hebt bereikt?
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.")
Dit zou resulteren in het volgende:
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.
dit zal werken aangezien leeftijd nooit een waarde zal hebben die onzinnig is en de code de logica van uw “bedrijfsproces” volgt
Antwoord 3, autoriteit 3%
Hoewel het geaccepteerde antwoord verbazingwekkend is. Ik wil ook graag een snelle hack voor dit probleem delen. (Dit lost ook het negatieve leeftijdsprobleem op.)
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. Deze code is voor python 3.x.
Antwoord 4, autoriteit 2%
Met Click:
Clickis een bibliotheek voor opdrachtregelinterfaces en biedt functionaliteit voor het vragen van een geldig antwoord van een gebruiker.
Eenvoudig voorbeeld:
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
Merk op hoe deze de tekenreekswaarde automatisch naar een drijver is geconverteerd.
Controleren of een waarde binnen een bereik is:
Er zijn verschillende aangepaste typen verstrekt. Om een cijfer in een specifiek bereik te krijgen, kunnen we IntRange
gebruiken:
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
We kunnen ook slechts één van de limieten specificeren, min
of 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
Lidmaatschapstests:
Gebruik click.Choice
Type. Standaard is deze cheque hoofdlettergevoelig.
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
Werken met paden en bestanden:
Met behulp van een click.Path
-type kunnen we controleren op bestaande paden en deze ook oplossen:
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
Het lezen en schrijven van bestanden kan worden gedaan door 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!
Andere voorbeelden:
Wachtwoordbevestiging:
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
Standaardwaarden:
In dit geval, eenvoudig op invoeren kbd>(of welke toets die u gebruikt) zonder een waarde in te voeren, geeft u een standaardinformatie:
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
Antwoord 5
Ja, ik ben 6 jaar te laat met de🎉 maar deze vraag verdient een meer actueel antwoord.
Scheiding van zorgen
Ik ben een grote fan van de Unix-filosofie 'Doe één ding en doe het goed'. Bij dit soort problemen is het beter om het probleem op te splitsen in
- Vraag invoer met
get_input
totdat de invoer in orde is. - Bevestigen in functie
validator
. Je zou verschillende validators kunnen schrijven voor verschillende invoerquery's.
Vraag om input
Het kan zo simpel worden gehouden als (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)
Voorbeeld
In [2]: get_input('Give a positive number: ', myvalidator, 'Please, try again')
Give a positive number: foobar
Please, try again
Give a positive number: -10
Please, try again
Give a positive number: 42
Out[2]: '42'
Python 3.8+ Opmerking
In Python 3.8+ zou je de walrus-operator kunnen gebruiken
def get_input(prompt, validator, on_validationerror):
while not validator(value := input(prompt)):
print(on_validationerror)
return value
Antwoord 6
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."
7
bouwen op Daniel Q's en Patrick Artner's uitstekende suggesties,
Hier is een nog gegeneraliseerde oplossing.
# 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)
Ik heb gekozen voor expliciete if
en raise
uitspraken in plaats van een assert
,
Omdat beweringcontrole kan worden uitgeschakeld,
overwegende dat validatie altijd moet zijn om robuustheid te bieden.
Dit kan worden gebruikt om verschillende soorten input te krijgen,
met verschillende validatie-omstandigheden.
Bijvoorbeeld:
# 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!"})
of, om de oorspronkelijke vraag te beantwoorden:
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.")
8
Gebruik try-behalve om de fout aan te pakken en opnieuw te herhalen:
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")
9
Probeer deze: -
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')
10
Hoewel een try
/except
-blok zal werken, zou een veel snellere en schonere manier om deze taak te volbrengen het gebruik van 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.")
Antwoord 11
Goede vraag! U kunt hiervoor de volgende code proberen. =)
Deze code gebruikt ast.literal_eval()om vinden het gegevenstype van de invoer(age
). Dan volgt het het volgende algoritme:
Vraag de gebruiker om haar/zijn
age
in te voeren.1.1. Als
age
het gegevenstypefloat
ofint
is:
Controleer of
age>=18
. Alsage>=18
, druk dan de juiste uitvoer af en sluit af.Controleer of
0<age<18
. Als0<age<18
, druk dan de juiste uitvoer af en sluit af.Indien
age<=0
, vraag de gebruiker om opnieuw een geldig getal voor leeftijd in te voeren, (dwzga terug naar stap 1.)1.2. Als
age
niet het gegevenstypefloat
ofint
is, vraag de gebruiker dan om zijn/haar leeftijd opnieuw in te voeren (dwzga terug naar stap 1.)
Hier is de 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.")
Antwoord 12
Je kunt altijd eenvoudige if-else-logica toepassen en nog een if
-logica aan je code toevoegen, samen met een for
-lus.
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
Dit wordt een oneindig toilet en je wordt gevraagd de leeftijd voor onbepaalde tijd in te voeren.
Antwoord 13
Onderstaande code kan helpen.
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='')
Als je maximale pogingen wilt hebben, zeg 3, gebruik dan onderstaande code
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='')
Opmerking: dit gebruikt recursie.
Antwoord 14
Je kunt meer algemene logica schrijven zodat de gebruiker slechts een bepaald aantal keren hoeft in te voeren, aangezien dezelfde use-case zich voordoet in veel toepassingen in de echte wereld.
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.
Antwoord 15
Je kunt het invoerstatement een while-True-lus maken, zodat het herhaaldelijk om invoer van de gebruiker vraagt en die lus vervolgens verbreken als de gebruiker het gewenste antwoord invoert. En je kunt proberen en behalve blokken gebruiken om ongeldige reacties af te handelen.
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.")
De variabele var is zo dat als de gebruiker een tekenreeks invoert in plaats van een geheel getal, het programma niet teruggeeft "Je kunt niet stemmen in de Verenigde Staten."
Antwoord 16
Gebruik de instructie "while" totdat de gebruiker een echte waarde invoert en als de invoerwaarde geen getal of een null-waarde is, sla deze dan over en probeer het opnieuw, enzovoort.
Ik heb bijvoorbeeld geprobeerd uw vraag echt te beantwoorden. Als we aannemen dat onze leeftijd tussen 1 en 150 ligt, wordt de invoerwaarde geaccepteerd, anders is het een verkeerde waarde.
Voor het beëindigen van het programma kan de gebruiker de 0-toets gebruiken en deze als een waarde invoeren.
Opmerking: lees opmerkingen bovenaan de 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.")
Antwoord 17
Nog een oplossing voor het gebruik van invoervalidatie met behulp van een aangepaste ValidationError
en een (optionele) bereikvalidatie voor integere invoer:
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))
Gebruik:
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)
Uitgang:
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
Antwoord 18
Persistente gebruikersinvoer met behulp van recursieve functie:
String
def askName():
return input("Write your name: ").strip() or askName()
name = askName()
Geheel getal
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
en tot slot de vraagvereiste:
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)
Antwoord 19
Gebruik isdigit()
om te controleren of een tekenreeks een geldig geheel getal vertegenwoordigt.
Je zou een recursieve functie kunnen gebruiken.
def ask():
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
return ask()
return int(answer)
Gdp = ask()
Of een while-lus
while True:
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
continue
Gbp = int(answer)
Antwoord 20
De eenvoudige oplossing zou zijn:
while True:
age = int(input("Please enter your age: "))
if (age<=0) or (age>120):
print('Sorry, I did not understand that.Please try again')
continue
else:
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.")
break
Uitleg van bovenstaande code:
Om een geldige leeftijd te krijgen, moet deze positief zijn en mag deze niet ouder zijn dan de normale fysieke leeftijd, bijvoorbeeld de maximale leeftijd is 120.
Dan kunnen we de gebruiker om leeftijd vragen en als de leeftijdsinvoer negatief is of hoger dan 120, beschouwen we dit als ongeldige invoer en vragen we de gebruiker om het opnieuw te proberen.
Zodra de geldige invoer is ingevoerd, controleren we (met behulp van geneste if-else-verklaring) of de leeftijd >=18 is of omgekeerd en drukken we een bericht af of de gebruiker in aanmerking komt om te stemmen