Cara paling sederhana untuk mencapai ini adalah dengan meletakkan input
metode dalam loop sementara. Gunakan continue
saat Anda mendapat input yang buruk, dan break
keluar dari lingkaran saat Anda puas.
Saat Masukan Anda Mungkin Mendapat Pengecualian
Gunakan try
danexcept
untuk mendeteksi ketika pengguna memasukkan data yang tidak dapat diuraikan.
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.")
Menerapkan Aturan Validasi Anda Sendiri
Jika Anda ingin menolak nilai yang Python berhasil parse, Anda bisa menambahkan logika validasi Anda sendiri.
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
Menggabungkan Penanganan Eksepsi dan Validasi Kustom
Kedua teknik di atas dapat digabungkan menjadi satu loop.
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.")
Enkapsulasi Semuanya dalam suatu Fungsi
Jika Anda perlu meminta banyak nilai berbeda kepada pengguna, mungkin berguna untuk menempatkan kode ini dalam suatu fungsi, jadi Anda tidak perlu mengetik ulang setiap kali.
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: ")
Menyatukan Semuanya
Anda dapat memperluas ide ini untuk membuat fungsi input yang sangat umum:
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
Dengan penggunaan seperti:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
Perangkap Umum, dan Mengapa Anda Harus Menghindarinya
Penggunaan Redundant input
Statement Redundant
Metode ini berfungsi tetapi umumnya dianggap sebagai gaya yang buruk:
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): ")
Awalnya mungkin terlihat menarik karena lebih pendek dari while True
metodenya, tetapi melanggar prinsip Jangan Ulangi Pengembangan Perangkat Lunak. Ini meningkatkan kemungkinan bug di sistem Anda. Bagaimana jika Anda ingin backport ke 2.7 dengan mengubah input
ke raw_input
, tetapi secara tidak sengaja hanya mengubah yang pertama di input
atas? Itu adalahSyntaxError
hanya menunggu untuk terjadi.
Rekursi Akan Memukul Tumpukan Anda
Jika Anda baru saja belajar tentang rekursi, Anda mungkin tergoda untuk menggunakannya get_non_negative_int
sehingga Anda dapat membuang loop sementara.
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
Ini tampaknya berfungsi dengan baik sebagian besar waktu, tetapi jika pengguna memasukkan data yang tidak valid cukup kali, skrip akan diakhiri dengan a RuntimeError: maximum recursion depth exceeded
. Anda mungkin berpikir "tidak ada orang bodoh yang akan membuat 1000 kesalahan berturut-turut", tetapi Anda meremehkan kecerdikan orang bodoh!
input
per loop dan loop akan menjadi sangat pendek, tetapi kondisinya mungkin menjadi cukup lama ...Mengapa Anda melakukan
while True
dan kemudian keluar dari lingkaran ini sementara Anda juga bisa memasukkan persyaratan Anda dalam pernyataan sementara karena semua yang Anda inginkan adalah berhenti setelah Anda memiliki usia?Ini akan menghasilkan sebagai berikut:
ini akan berfungsi karena usia tidak akan pernah memiliki nilai yang tidak masuk akal dan kode mengikuti logika "proses bisnis" Anda
sumber
Padahal jawaban yang diterima luar biasa. Saya juga ingin membagikan peretasan cepat untuk masalah ini. (Ini menangani masalah usia negatif juga.)
PS Kode ini untuk python 3.x.
sumber
def
saja.def f(age):
jauh lebih jelas daripadaf = lambda age:
Jadi, saya bermain-main dengan sesuatu yang mirip dengan ini baru-baru ini, dan saya datang dengan solusi berikut, yang menggunakan cara mendapatkan input yang menolak sampah, bahkan sebelum diperiksa dengan cara yang logis.
read_single_keypress()
kesopanan https://stackoverflow.com/a/6599441/4532996Anda dapat menemukan modul lengkap di sini .
Contoh:
Perhatikan bahwa sifat implementasi ini adalah menutup stdin segera setelah sesuatu yang bukan angka dibaca. Saya tidak menekan enter setelah
a
, tetapi saya perlu setelah angka.Anda bisa menggabungkan ini dengan
thismany()
fungsi dalam modul yang sama hanya memungkinkan, katakanlah, tiga digit.sumber
Pendekatan fungsional atau " lihat ibu tidak ada loop! ":
atau jika Anda ingin memisahkan pesan "input buruk" dari prompt input seperti pada jawaban lain:
Bagaimana cara kerjanya?
itertools.chain
danitertools.repeat
akan menciptakan iterator yang akan menghasilkan string"Enter a number: "
sekali, dan"Not a number! Try again: "
dalam jumlah tak terbatas:replies = map(input, prompts)
- di sinimap
akan menerapkan semuaprompts
string dari langkah sebelumnya keinput
fungsi. Misalnya:filter
danstr.isdigit
memfilter string yang hanya berisi digit: Dan untuk mendapatkan hanya string digit-only pertama yang kami gunakannext
.Aturan validasi lainnya:
Metode string: Tentu saja Anda dapat menggunakan metode string lain seperti
str.isalpha
hanya mendapatkan string alfabet, ataustr.isupper
hanya mendapatkan huruf besar. Lihat dokumen untuk daftar lengkap.Pengujian keanggotaan:
Ada beberapa cara berbeda untuk melakukannya. Salah satunya dengan menggunakan
__contains__
metode:Perbandingan angka:
Ada metode perbandingan berguna yang bisa kita gunakan di sini. Misalnya, untuk
__lt__
(<
):Atau, jika Anda tidak suka menggunakan metode dunder (dunder = double-underscore), Anda selalu dapat mendefinisikan fungsi Anda sendiri, atau menggunakan yang dari
operator
modul.Jalur keberadaan:
Di sini orang dapat menggunakan
pathlib
perpustakaan danPath.exists
metodenya:Membatasi jumlah percobaan:
Jika Anda tidak ingin menyiksa pengguna dengan menanyakan sesuatu sesuatu dalam jumlah tak terbatas, Anda dapat menentukan batas dalam panggilan
itertools.repeat
. Ini dapat dikombinasikan dengan memberikan nilai default kenext
fungsi:Input data preprocessing:
Terkadang kami tidak ingin menolak input jika pengguna secara tidak sengaja memasukkannya dalam CAPS atau dengan spasi di awal atau akhir dari string. Untuk memperhitungkan kesalahan sederhana ini, kita dapat memproses ulang input data dengan menerapkan
str.lower
danstr.strip
metode. Misalnya, untuk kasus pengujian keanggotaan, kode akan terlihat seperti ini:Dalam kasus ketika Anda memiliki banyak fungsi untuk digunakan untuk preprocessing, mungkin lebih mudah untuk menggunakan fungsi yang melakukan komposisi fungsi . Misalnya, menggunakan yang dari sini :
Menggabungkan aturan validasi:
Untuk kasus sederhana, misalnya, ketika program meminta usia antara 1 dan 120, orang bisa menambahkan yang lain
filter
:Tetapi dalam kasus ketika ada banyak aturan, lebih baik untuk mengimplementasikan fungsi yang melakukan konjungsi logis . Dalam contoh berikut ini saya akan menggunakan yang siap dari sini :
Sayangnya, jika seseorang membutuhkan pesan khusus untuk setiap kasus yang gagal, maka, saya khawatir, tidak ada yang cantik cara yang fungsional. Atau, setidaknya, saya tidak dapat menemukannya.
sumber
Menggunakan Klik :
Klik adalah pustaka untuk antarmuka baris perintah dan menyediakan fungsionalitas untuk meminta respons yang valid dari pengguna.
Contoh sederhana:
Perhatikan bagaimana ini mengubah nilai string menjadi float secara otomatis.
Memeriksa apakah suatu nilai berada dalam kisaran:
Ada berbagai jenis kustom yang disediakan. Untuk mendapatkan nomor dalam rentang tertentu, kita dapat menggunakan
IntRange
:Kami juga dapat menentukan satu saja dari batasan,
min
ataumax
:Pengujian keanggotaan:
Menggunakan
click.Choice
tipe. Secara default, pemeriksaan ini peka terhadap huruf besar-kecil.Bekerja dengan jalur dan file:
Menggunakan
click.Path
tipe kita dapat memeriksa jalur yang ada dan juga menyelesaikannya:Membaca dan menulis file dapat dilakukan dengan
click.File
:Contoh lain:
Konfirmasi kata kunci:
Nilai dasar:
Dalam hal ini, cukup menekan Enter(atau tombol apa pun yang Anda gunakan) tanpa memasukkan nilai, akan memberi Anda nilai default:
sumber
sumber
Berdasarkan saran Daniel Q dan Patrick Artner yang luar biasa, inilah solusi yang lebih umum.
Saya memilih pernyataan yang eksplisit
if
danraise
bukanassert
, karena pemeriksaan pernyataan dapat dimatikan, sedangkan validasi harus selalu aktif untuk memberikan ketahanan.Ini dapat digunakan untuk mendapatkan berbagai jenis input, dengan kondisi validasi yang berbeda. Sebagai contoh:
Atau, untuk menjawab pertanyaan awal:
sumber
Coba yang ini:-
sumber
Sementara a
try
/except
block akan bekerja, cara yang jauh lebih cepat dan lebih bersih untuk menyelesaikan tugas ini adalah dengan menggunakannyastr.isdigit()
.sumber
Pertanyaan bagus! Anda dapat mencoba kode berikut untuk ini. =)
Kode ini menggunakan ast.literal_eval () untuk menemukan tipe data dari input (
age
). Kemudian mengikuti algoritma berikut:Ini kodenya.
sumber
Anda selalu dapat menerapkan logika if-else sederhana dan menambahkan satu lagi
if
logika ke kode Anda bersama dengan satufor
loop.Ini akan menjadi toilet tanpa batas dan Anda akan diminta memasuki usia, tanpa batas.
sumber
Anda dapat menulis logika yang lebih umum untuk memungkinkan pengguna untuk memasukkan hanya beberapa kali tertentu, karena kasus penggunaan yang sama muncul di banyak aplikasi dunia nyata.
sumber
Anda dapat membuat pernyataan input sementara True loop sehingga berulang kali meminta input pengguna dan kemudian istirahat loop itu jika pengguna memasukkan respons yang Anda inginkan. Dan Anda dapat menggunakan blok coba dan kecuali untuk menangani respons yang tidak valid.
Variabel var hanya agar jika pengguna memasukkan string, bukan bilangan bulat, program tidak akan mengembalikan "Anda tidak dapat memilih di Amerika Serikat."
sumber
Gunakan pernyataan "sementara" sampai pengguna memasukkan nilai sebenarnya dan jika nilai input bukan angka atau itu adalah nilai nol lewati saja dan cobalah untuk bertanya lagi dan seterusnya. Sebagai contoh, saya mencoba menjawab pertanyaan Anda. Jika kita mengira usia kita adalah antara 1 dan 150 maka nilai input diterima, kalau tidak itu nilai yang salah. Untuk mengakhiri program, pengguna dapat menggunakan kunci 0 dan memasukkannya sebagai nilai.
sumber
Satu lagi solusi untuk menggunakan validasi input menggunakan validasi rentang
ValidationError
dan pilihan (opsional) untuk input integer:Pemakaian:
Keluaran:
sumber
Berikut ini adalah solusi yang lebih bersih dan lebih umum yang menghindari berulang jika / blok lain: menulis fungsi yang mengambil (Kesalahan, prompt kesalahan) berpasangan dalam kamus dan melakukan semua pemeriksaan nilai Anda dengan pernyataan.
Pemakaian:
sumber
Input pengguna persisten menggunakan fungsi rekursif :
Tali
Bilangan bulat
dan akhirnya, persyaratan pertanyaan:
sumber
Solusi sederhana adalah:
Penjelasan kode di atas: Agar usia yang valid, itu harus positif dan tidak boleh lebih dari usia fisik normal, misalnya misalnya usia maksimum adalah 120.
Kemudian kita dapat menanyakan usia pengguna dan jika input usia negatif atau lebih dari 120, kami menganggapnya sebagai input yang tidak valid dan meminta pengguna untuk mencoba lagi.
Setelah input yang valid dimasukkan, kami melakukan pemeriksaan (menggunakan pernyataan if-else bersarang) apakah usianya> = 18 atau sebaliknya dan mencetak pesan apakah pengguna berhak memilih
sumber
mengambil input sebagai string dan menggunakan isdigit () untuk memeriksa input hanya memiliki digit, tidak kosong, tidak boleh -ve
sumber