Kullanıcıdan geçerli bir yanıt verene kadar girdi istemek

Apr 25 2014

Kullanıcıdan bir girdi kabul eden bir program yazıyorum.

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

Program, kullanıcı anlamlı veriler girdiği sürece beklendiği gibi çalışır.

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

Ancak kullanıcı geçersiz veri girerse başarısız olur:

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'

Kilitlenmek yerine, programın girişi tekrar istemesini istiyorum. Bunun gibi:

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!

Anlamsız veriler girildiğinde programın çökmek yerine geçerli girdiler istemesini nasıl sağlayabilirim?

Bu bağlamda -1geçerli intama anlamsız olan gibi değerleri nasıl reddedebilirim ?

Yanıtlar

776 Kevin Apr 25 2014 at 20:31

Bunu başarmanın en basit yolu, inputyöntemi bir süre döngüsüne koymaktır . Kullanım continuekötü girişini olsun ve breakdöngünün dışında size şüpheniz yoksa.

Girişiniz Ne Zaman Bir İstisna Yaratabilir?

Kullanıcının ayrıştırılamayan verileri girdiğini algılamak için tryveexcept kullanın .

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

Kendi Doğrulama Kurallarınızı Uygulama

Python'un başarıyla ayrıştırabildiği değerleri reddetmek istiyorsanız, kendi doğrulama mantığınızı ekleyebilirsiniz.

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

İstisna İşlemeyi ve Özel Doğrulamayı Birleştirme

Yukarıdaki tekniklerin her ikisi de tek bir döngüde birleştirilebilir.

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

Hepsini bir Fonksiyonda Kapsülleme

Kullanıcınızdan çok sayıda farklı değer istemeniz gerekiyorsa, bu kodu bir işleve koymanız faydalı olabilir, böylece her seferinde yeniden yazmanıza gerek kalmaz.

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

Hepsini bir araya koy

Çok genel bir girdi işlevi yapmak için bu fikri genişletebilirsiniz:

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

Gibi kullanımlarla:

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

Yaygın Tuzaklar ve Neden Onlardan Kaçınmalısınız

Gereksiz inputİfadelerin Gereksiz Kullanımı

Bu yöntem işe yarıyor, ancak genellikle kötü stil olarak kabul ediliyor:

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

Başlangıçta while Trueyöntemden daha kısa olduğu için çekici görünebilir , ancak yazılım geliştirmenin Kendini Tekrar Etme ilkesini ihlal ediyor . Bu, sisteminizdeki hata olasılığını artırır. Ya olarak değiştirerek 2.7'ye backport inputyapmak raw_input, ancak kazara sadece inputyukarıdakini değiştirmek istiyorsanız? Bu SyntaxErrorsadece gerçekleşmesini bekliyor.

Özyineleme Yığını Patlatacak

Özyinelemeyi yeni öğrendiyseniz, onu kullanmak isteyebilirsiniz, get_non_negative_intböylece while döngüsünden kurtulabilirsiniz.

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

Bu, çoğu zaman iyi çalışıyor gibi görünüyor, ancak kullanıcı yeterince geçersiz veri girerse, komut dosyası bir RuntimeError: maximum recursion depth exceeded. "Hiçbir aptal arka arkaya 1000 hata yapmaz" diye düşünebilirsiniz, ama aptalların yaratıcılığını küçümsüyorsunuz!

46 StevenStip Jan 14 2016 at 19:43

Neden bir yapıp while Truesonra bu döngüden çıkarsınız ki, aynı zamanda gereksinimlerinizi while deyimine koyabilirsiniz, çünkü tek istediğiniz yaşınız olduğunda durmaktır?

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

Bu, aşağıdakilere neden olur:

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.

bu işe yarayacak çünkü yaş hiçbir zaman anlamsız bir değere sahip olmayacak ve kod "iş sürecinizin" mantığını takip ediyor

26 aaveg Jun 29 2015 at 06:29

Kabul edilen cevap şaşırtıcı olsa da. Ayrıca bu sorun için hızlı bir hack paylaşmak istiyorum. (Bu, negatif yaş sorununu da çözer.)

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 Bu kod python 3.x içindir.

17 Georgy May 10 2019 at 23:47

İşlevsel yaklaşım veya " anne bak, döngü yok! ":

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

veya diğer yanıtlarda olduğu gibi bir giriş isteminden ayrılmış bir "hatalı giriş" mesajına sahip olmak istiyorsanız:

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

O nasıl çalışır?

  1. prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
    
    Bu kombinasyonu itertools.chainve itertools.repeatdizeleri verecektir bir yineleyici yaratacak "Enter a number: "bir kez ve "Not a number! Try again: "zaman sonsuz sayıda:
    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)- burada önceki adımdaki maptüm promptsdizeler inputişleve uygulanacaktır. Örneğin:
    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. Yalnızca rakam içeren dizeleri filtrelemek için filterve kullanırız str.isdigit:
    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...
    
    Ve sadece ilk rakamlardan oluşan dizeyi elde etmek için kullandığımız next.

Diğer doğrulama kuralları:

  1. Dize yöntemleri: Elbette str.isalpha, yalnızca alfabetik dizeler str.isupperelde etmek veya yalnızca büyük harf almak gibi diğer dize yöntemlerini kullanabilirsiniz . Tam liste için belgelere bakın .

  2. Üyelik testi:
    Bunu gerçekleştirmenin birkaç farklı yolu vardır. Bunlardan biri __contains__yöntemi kullanmaktır :

    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. Sayı karşılaştırması:
    Burada kullanabileceğimiz yararlı karşılaştırma yöntemleri vardır. Örneğin, __lt__( <) için:

    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
    

    Ya da, dunder yöntemlerini kullanmayı sevmiyorsanız (dunder = çift alt çizgi), her zaman kendi işlevinizi tanımlayabilir veya operatormodülden olanları kullanabilirsiniz .

  4. Yol varlığı:
    Burada pathlibkitaplık ve Path.existsyöntemi kullanılabilir:

    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
    

Deneme sayısını sınırlama:

Bir kullanıcıya sonsuz sayıda bir şey sorarak işkence yapmak istemiyorsanız, bir çağrıda bir sınır belirleyebilirsiniz itertools.repeat. Bu, nextişleve varsayılan bir değer sağlamakla birleştirilebilir :

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!

Giriş verilerini ön işleme:

Bazen, kullanıcı yanlışlıkla CAPS İÇİNDE sağladıysa veya dizenin başında veya sonunda bir boşluk bıraktıysa , bir girişi reddetmek istemeyiz . Bu basit hataları hesaba katmak için, girdi verilerini str.lowerve str.stripyöntemlerini uygulayarak önceden işleyebiliriz . Örneğin, üyelik testi durumunda kod şu şekilde görünecektir:

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

Önişleme için kullanabileceğiniz çok sayıda işleviniz olması durumunda, bir işlev bileşimi gerçekleştiren bir işlevi kullanmak daha kolay olabilir . Örneğin, buradakini kullanarak :

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

Doğrulama kurallarını birleştirmek:

Basit bir durum için, örneğin, program 1 ile 120 arasında yaş sorduğunda, biri başka bir tane ekleyebilir 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)

Ancak birçok kuralın olduğu durumda, mantıksal bir birleşim gerçekleştiren bir işlevi uygulamak daha iyidir . Aşağıdaki örnekte buradan hazır olanı kullanacağım :

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

Ne yazık ki, başarısız olan her vaka için birisinin özel bir mesaja ihtiyacı varsa, o zaman korkarım, oldukça işlevsel bir yol yoktur . Ya da en azından bir tane bulamadım.

13 cat Jan 31 2016 at 10:47

Son zamanlarda buna benzer bir şeyle uğraşıyordum ve mantıksal bir şekilde kontrol edilmeden önce gereksiz verileri reddeden bir girdi elde etmenin bir yolunu kullanan aşağıdaki çözümü buldum.

read_single_keypress()nezaket 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()

Modülün tamamını burada bulabilirsiniz .

Misal:

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

Bu gerçeklenmenin doğası gereği, basamak olmayan bir şey okunduğu anda stdin'i kapatır. Daha sonra enter tuşuna basmadım aama rakamlardan sonra girmem gerekiyordu.

Bunu, thismany()yalnızca, örneğin üç basamağa izin vermek için aynı modüldeki işlevle birleştirebilirsiniz .

12 Georgy May 11 2019 at 03:17

Click Kullanımı :

Tıklama , komut satırı arayüzleri için bir kitaplıktır ve bir kullanıcıdan geçerli bir yanıt istemek için işlevsellik sağlar.

Basit örnek:

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

Dize değerini otomatik olarak bir kayan noktaya nasıl dönüştürdüğüne dikkat edin.

Bir değerin bir aralıkta olup olmadığını kontrol etme:

Sağlanan farklı özel türler vardır . Belirli bir aralıkta bir sayı elde etmek için kullanabiliriz 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

Ayrıca sınırlardan yalnızca birini de belirtebiliriz minveya 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

Üyelik testi:

click.ChoiceTür kullanarak . Varsayılan olarak bu kontrol büyük / küçük harfe duyarlıdır.

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

Yollar ve dosyalarla çalışma:

Bir click.Pathtür kullanarak mevcut yolları kontrol edebilir ve bunları çözebiliriz:

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

Dosyaları okuma ve yazma şu şekilde yapılabilir 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!

Diğer örnekler:

Şifre onayı:

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

Varsayılan değerler:

Bu durumda, Enterbir değer girmeden (veya kullandığınız herhangi bir tuşa) basmanız size varsayılan bir değer verecektir:

number = click.prompt('Please enter a number', type=int, default=42)
print(number)
Please enter a number [42]: 
 a
Error: a is not a valid integer
Please enter a number [42]: 
 
42
3 ojasmohril Jun 23 2016 at 17:34
def validate_age(age):
    if age >=0 :
        return True
    return False

while True:
    try:
        age = int(raw_input("Please enter your age:"))
        if validate_age(age): break
    except ValueError:
        print "Error: Invalid age."
2 JoãoManuelRodrigues Nov 28 2018 at 21:52

Daniel Q'nun ve Patrick Artner'ın mükemmel önerilerine dayanarak, işte daha da genelleştirilmiş bir çözüm.

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

Bir yerine açık ifve raiseifadeleri tercih ettim assert, çünkü onaylama kontrolü kapatılabilir, oysa sağlamlık sağlamak için doğrulama her zaman açık olmalıdır.

Bu, farklı doğrulama koşulları ile farklı türde girdiler elde etmek için kullanılabilir. Örneğin:

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

Veya orijinal soruyu cevaplamak için:

age = validate_input("Please enter your age: ",
        cast=int, cond=lambda a:0<=a<150,
        onerror={ValidationError: "Enter a plausible age, please!",
                 ValueError: "Enter an integer, please!"})
if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")
1 PratikAnand Apr 30 2017 at 16:29

Bunu dene:-

def takeInput(required):
  print 'ooo or OOO to exit'
  ans = raw_input('Enter: ')

  if not ans:
      print "You entered nothing...!"
      return takeInput(required) 

      ##  FOR Exit  ## 
  elif ans in ['ooo', 'OOO']:
    print "Closing instance."
    exit()

  else:
    if ans.isdigit():
      current = 'int'
    elif set('[~!@#$%^&*()_+{}":/\']+$').intersection(ans):
      current = 'other'
    elif isinstance(ans,basestring):
      current = 'str'        
    else:
      current = 'none'

  if required == current :
    return ans
  else:
    return takeInput(required)

## pass the value in which type you want [str/int/special character(as other )]
print "input: ", takeInput('str')
1 np8 Oct 30 2020 at 14:12

Evet, 🎉'dan 6 yıl geciktim ama bu soru daha güncel bir cevabı hak ediyor.

Endişelerin ayrılması

Unix felsefesinin büyük bir hayranıyım "Bir şeyi yap ve onu iyi yap" . Bu tür bir problemde, problemi ikiye bölmek daha iyi bir uygulamadır.

  • Giriş get_inputtamam olana kadar giriş isteyin .
  • validatorİşlev olarak doğrulayın . Farklı giriş sorguları için farklı doğrulayıcılar yazabilirsiniz.

Girdi sormak

(Python 3+) kadar basit tutulabilir

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)

Misal

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+ Not

Python 3.8+ sürümünde mors operatörünü kullanabilirsiniz

def get_input(prompt, validator, on_validationerror):
    while not validator(value := input(prompt)):
        print(on_validationerror)
    return value 
2Cubed May 31 2016 at 03:47

A try/ exceptblock çalışırken, bu görevi gerçekleştirmenin çok daha hızlı ve temiz bir yolu kullanmak olacaktır str.isdigit().

while True:
    age = input("Please enter your age: ")
    if age.isdigit():
        age = int(age)
        break
    else:
        print("Invalid number '{age}'. Try again.".format(age=age))

if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")
SiddharthSatpathy Dec 18 2018 at 13:17

İyi soru! Bunun için aşağıdaki kodu deneyebilirsiniz. =)

Bu kod, kullanımları ast.literal_eval () için giriş veri yapısını ( age). Ardından aşağıdaki algoritmayı takip eder:

  1. Kullanıcıdan kendisini girmesini isteyin age.

    1.1. Eğer agebir floatya da intveri türü:

    • Kontrol edin age>=18. Eğer age>=18, uygun çıktıyı yazdırın ve çıkın.

    • Kontrol edin 0<age<18. Eğer 0<age<18, uygun çıktıyı yazdırın ve çıkın.

    • Eğer age<=0, yaş için geçerli bir sayı tekrar girişine kullanıcıya sor, ( yani geri adım 1. gidin)

    1.2. Eğer agedeğil floatya intveri türü, daha sonra onu / yeniden kendi yaş (giriş için kullanıcı sormak yani 1. adımda geri dönmek)

İşte kod.

from ast import literal_eval

''' This function is used to identify the data type of input data.'''
def input_type(input_data):
    try:
        return type(literal_eval(input_data))
    except (ValueError, SyntaxError):
        return str

flag = True

while(flag):
    age = raw_input("Please enter your age: ")

    if input_type(age)==float or input_type(age)==int:
        if eval(age)>=18: 
            print("You are able to vote in the United States!") 
            flag = False 
        elif eval(age)>0 and eval(age)<18: 
            print("You are not able to vote in the United States.") 
            flag = False
        else: print("Please enter a valid number as your age.")

    else: print("Sorry, I didn't understand that.") 
Ep1c1aN Jul 01 2019 at 16:36

Her zaman basit aksi takdirde ifmantığını uygulayabilir ve kodunuza bir fordöngü ile birlikte bir mantık daha ekleyebilirsiniz .

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

Bu sonsuz bir tuvalet olacak ve sizden süresiz olarak çağa girmeniz istenecek.

Liju Aug 17 2020 at 15:24

Aşağıdaki kod yardımcı olabilir.

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

Maksimum deneme yapmak istiyorsanız, 3 diyelim, aşağıdaki kodu kullanın

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

Not: Bu, özyinelemeyi kullanır.

behnaz.sheikhi Sep 09 2020 at 19:30

Hatayı işlemek ve tekrarlamak için try-hariç'i kullanın:

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