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 Функция имеет две совершенно разные обязанности:

  1. Обработка пользовательского ввода и проверки; а также
  2. Расчет чисел Фибоначчи.

От имени, я бы сказал, что это должно быть сделано только № 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 выглядит как совершенно допустимое исключение для поднятия здесь; вам может не понадобиться более конкретный класс вообще.

Другие вопросы по тегам