Python как сделать исключение для неположительных чисел
Как я могу вызвать исключение, чтобы поймать неположительные входные данные? Прямо сейчас ничего не печатается, если я введу отрицательное число
"""
Generate fibonacci sequence to the nth digit
"""
def fib(n):
try:
if n <= 0:
raise Exception
prev = 0
curr = 1
for terms in range(0, int(n)):
nxt = prev + curr
print str(curr),
prev = curr
curr = nxt
except ValueError or Exception:
new = raw_input("Invalid input. Please enter a positive integer: ")
fib(new)
n = raw_input("Enter number of terms: ")
fib(n)
4 ответа
Как говорит Джон, это гораздо лучшая стратегия проектирования, чтобы отделить сбор данных от основного вычисления Фибоначчи. Кроме того, обычно лучше использовать простой цикл, чем использовать рекурсивный вызов (вызов функции внутри себя), если только вам действительно не нужна рекурсия (например, при обработке рекурсивной структуры данных, такой как дерево каталогов).
Вот модифицированная версия вашего кода. Я сделал несколько других незначительных изменений. В Python нам не нужна временная переменная, такая как nxt
сделать основной расчет Фибоначчи. Вместо этого мы используем присвоение кортежей, чтобы мы могли обновить curr
и сохранить старое curr
в prev
в один шаг.
def input_positive_integer(prompt=''):
""" Get a positive integer from the user """
while True:
try:
n = int(raw_input(prompt))
if n <= 0:
raise ValueError
break
except ValueError:
print "Invalid input.",
prompt = "Please enter a positive integer: "
return n
def fib(n):
""" Print n terms of the Fibonacci sequence """
prev, curr = 0, 1
for terms in range(n):
print curr,
prev, curr = curr, prev + curr
n = input_positive_integer("Enter number of terms: ")
fib(n)
тестовое задание
Enter number of terms: -4
Invalid input. Please enter a positive integer: q
Invalid input. Please enter a positive integer: 2.5
Invalid input. Please enter a positive integer: 5
1 1 2 3 5
except ValueError or Exception
Правильный синтаксис для этого except (ValueError, Exception)
Обратите внимание, что все исключения наследуются от Exception
это может плохо себя вести.
Вам лучше не поднимать и пытаться поймать общее исключение. Вместо этого поднимите уже пойманный ValueError
:
def fib(n):
try:
if n <= 0:
raise ValueError
.
.
.
except ValueError:
.
.
.
Я думаю, что основная проблема заключается в том, что ваш fib
Функция имеет две совершенно разные обязанности:
- Обработка пользовательского ввода и проверки; а также
- Расчет чисел Фибоначчи.
От имени, я бы сказал, что это должно быть сделано только № 2!
Вместо этого структурируйте вашу программу так:
def positive_integer():
"""Loops until the user enters a positive integer."""
...
def fib(n):
"""Prints first n Fibonacci numbers."""
if n < 0:
raise ValueError
prev = 0
curr = 1
for terms in range(n): # note simplification here
nxt = prev + curr
print str(curr),
prev = curr
curr = nxt
fib(positive_integer())
Теперь у вас есть две функции, каждая из которых несет четкую ответственность. Это делает каждый менее сложным; range
вызов теперь стал проще, например, так как он может предполагать n
уже является целым числом (и если нет, пользователь получает разумный TypeError
рассказать им, что пошло не так).
Для записи positive_input
см. Запрос пользователя для ввода, пока он не даст правильный ответ; цикл лучше рекурсии для этого.
В качестве дальнейшего рефакторинга, вы можете сократить три строки
nxt = prev + curr
prev = curr
curr = nxt
только один:
prev, curr = curr, curr + prev
Также обратите внимание, что, как правило, вы должны сохранить try
блоки как можно короче и ваш except
пункты как можно более конкретными. Это делает их более полезными при чтении кода ("я думаю, что одна вещь может пойти не так, и в этом случае мы можем сделать это с этим") и означает, что законные проблемы не игнорируются. В частности, вы почти никогда не должны иметь дело напрямую с Exception
(либо в raise
или же except
), это слишком широкий случай, чтобы с ним справиться.
Чтобы перехватить несколько типов исключений, поместите их в кортеж. ValueError or Exception
является логическим выражением, которое оценивается как ValueError.
Также вы никогда не должны поднимать Exception, и вы никогда не должны его ловить. Определите свой собственный класс исключений.
class NonNegativeNumber(Error):
pass
...
except (ValueError, NonNegativeNumber):
Тем не менее, обратите внимание, что ValueError выглядит как совершенно допустимое исключение для поднятия здесь; вам может не понадобиться более конкретный класс вообще.