Самый простой способ добиться этого - поместить метод input
в цикл while. Используйте continue
, когда вы получаете плохой ввод, и break
выходят из цикла, когда вы удовлетворены.
Попробуйте попытаться и поймать , чтобы определить, когда пользователь вводит данные, которые не могут быть проанализированы.
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.")
Если вы хотите отклонить значения, которые Python может успешно проанализировать, вы можете добавить свою собственную логику проверки.
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
Оба вышеуказанных метода могут быть объединены в один цикл.
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.")
Если вам нужно спросить у вашего пользователя множество разных значений, может быть полезно поместить этот код в функция, поэтому вам не нужно повторно указывать ее каждый раз.
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: ")
Вы можете расширить эту идею, чтобы создать очень общую функцию ввода:
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
С использованием, например:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
input
Заявления Этот метод работает, но обычно считается неудовлетворительным:
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): ")
Первоначально он может выглядеть привлекательно, потому что он короче, чем метод while True
, но он нарушает Не повторяйте сам принцип разработки программного обеспечения. Это увеличивает вероятность ошибок в вашей системе. Что делать, если вы хотите выполнить резервное копирование до 2.7, изменив input
на raw_input
, но случайно измените только первый input
выше?
Если вы только что узнали о рекурсии, возможно, у вас возникнет соблазн использовать ее в get_non_negative_int
, поэтому вы можете избавиться от цикла while.
def get_non_negative_int(prompt):
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
return get_non_negative_int(prompt)
if value < 0:
print("Sorry, your response must not be negative.")
return get_non_negative_int(prompt)
else:
return value
Кажется, что он работает отлично в большинстве случаев, но если пользователь вводит неверные данные достаточно времени, сценарий заканчивается с помощью RuntimeError: maximum recursion depth exceeded
. Вы можете подумать, что «ни один дурак не допустит 1000 ошибок подряд», но вы недооцениваете изобретательность дураков!
Это функция Generator .
Генераторы - это функции, которые могут быть выведены и позже введены повторно. Их контекст (переменные привязки) будет сохранен во всех входах.
Вызов функции генератора не выполняет его тело немедленно; вместо этого возвращается объект-итератор для функции. Когда вызывается метод итератора
blockquote>next()
, тело функции генератора выполняется до первого выраженияyield
, которое указывает значение, которое должно быть возвращено из итератора, или, сyield*
, делегирует другую функцию генератора.
Историческое примечание:
Предложен синтаксис для
EcmaScript.next
.Дэйв Херман из Mozilla рассказал о EcmaScript.next . В 30:15 он рассказывает о генераторах.
Ранее он объясняет, как Mozilla экспериментально реализует предложенные языковые изменения, чтобы помочь руководству комитета. Дэйв работает в тесном контакте с Бренданом Эйчем, техническим директором Mozilla (я думаю) и оригинальным дизайнером JavaScript.
Более подробную информацию о рабочей группе рабочей среды EcmaScript можно найти по адресу: http: //wiki.ecmascript. org / doku.php? id = гармония: генераторы
Рабочая группа (TC-39) имеет общее согласие с тем, что EcmaScript.next должен иметь какое-то предложение итератора генератора, но это не final.
Вы не должны полагаться на это, показывая его без изменений в следующей версии языка, и даже если он не изменится, он, вероятно, не будет широко отображаться в других браузерах для while.
Обзор
Первоклассные сопрограммы, представленные как объекты, инкапсулирующие приостановленные контексты выполнения (т. е. активация функций). Предшествующий уровень техники: Python, Icon, Lua, Scheme, Smalltalk.
Примеры
«Бесконечная» последовательность чисел Фибоначчи (несмотря на поведение около 253):
function* fibonacci() { let [prev, curr] = [0, 1]; for (;;) { [prev, curr] = [curr, prev + curr]; yield curr; } }
Генераторы могут быть повторены в циклах:
for (n of fibonacci()) { // truncate the sequence at 1000 if (n > 1000) break; print(n); }
Генераторы являются итераторами:
blockquote>let seq = fibonacci(); print(seq.next()); // 1 print(seq.next()); // 2 print(seq.next()); // 3 print(seq.next()); // 5 print(seq.next()); // 8
Тип function*
выглядит как функция генератора для процессов, которые можно повторить. C # имеет такую функцию, как «yield return» , см. 1 и , см. 2
По сути, это возвращает каждое значение по одному на все, что итерация этого функция, поэтому их пример использования показывает его в цикле стиля foreach.
Это функция -генератора - и она так говорила на странице, которую вы цитируете, в комментарии, который вы заменили на «это интересная строка» ...
В основном это способ указать последовательности программным образом, чтобы они могли быть переданы, и элементы, к которым обратился индекс, без необходимости заранее вычислить всю последовательность (возможно, бесконечную по размеру).
for(;;)
)? Зачем использовать его в этом контексте? – Fergie 28 August 2013 в 08:22for(;;)
совпадает сwhile (true)
. Он используется в этом контексте, поскольку последовательность Фибоначчи является неограниченной последовательностью. – Mike Samuel 28 August 2013 в 08:37