【问题标题】:Python how to make an exception for non positive numbersPython如何对非正数进行例外处理
【发布时间】:2016-11-08 05:06:39
【问题描述】:

如何在此处引发异常以捕获非正输入?现在,如果我输入负数,则不会打印任何内容

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

【问题讨论】:

  • 您应该将负数测试移出 try - 您想要它会导致错误!另请注意,try 块应尽可能短,except 测试尽可能具体,否则会隐藏真正的问题。

标签: python exception numbers try-catch except


【解决方案1】:

except ValueError or Exception

正确的语法是except (ValueError, Exception),但请注意,由于所有异常都继承自Exception,这可能会出现问题。

您最好不要引发并尝试捕获一般异常。 相反,提出已经捕获的ValueError

def fib(n):
    try:
        if n <= 0:
            raise ValueError
    .
    .
    .
    except ValueError:
        .
        .
        .

【讨论】:

    【解决方案2】:

    要捕获多种异常类型,请将它们放在一个元组中。 ValueError or Exception 是一个布尔表达式,计算结果为 ValueError。

    此外,您永远不应该引发异常,并且永远不应该捕获它。定义您自己的自定义异常类。

    class NonNegativeNumber(Error):
        pass
    
    
    ...
    except (ValueError, NonNegativeNumber):
    

    但是,请注意 ValueError 似乎是在这里引发的完全有效的异常;您可能根本不需要更具体的课程。

    【讨论】:

    • ValueError or Exception 是一个布尔表达式,计算结果为ValueError(我相信你很清楚)。
    【解决方案3】:

    我认为这里的核心问题是您的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_inputAsking the user for input until they give a valid response;循环比递归更好。

    作为进一步的重构,你实际上可以削减三行

    nxt = prev + curr
    prev = curr
    curr = nxt
    

    只有一个:

    prev, curr = curr, curr + prev
    

    还请注意,一般而言,您应该使try 块尽可能短,except 子句尽可能具体。这使得它们在阅读代码时更加有用(“我认为这件事可能会出错,在这种情况下我们可以解决它”),这意味着合法的问题不会被悄悄地忽略。特别是,您几乎不应该直接与Exception 打交道(在raiseexcept 中),这种情况太宽泛,无法有效处理。

    【讨论】:

      【解决方案4】:

      正如 Jon 所说,将输入收集与核心斐波那契计算分开是一种更好的设计策略。此外,除非您真的需要递归(例如,在处理递归数据结构时,如目录树),否则使用简单循环通常比使用递归调用(调用自身内部的函数)更好。 .

      这是您的代码的修改版本。我做了一些其他的小改动。在 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
      

      【讨论】:

      • 快速问题:当您说“int(raw_input(prompt))”时,您是在将输入转换为整数吗?或者您是否在验证输入的类型
      • raw_input(prompt) 总是返回一个字符串。 int(some_string) 尝试将 some_string 转换为整数,但如果 some_string 不是表示整数的有效字符串,int 将引发 ValueError。所以在表达式int(raw_input(prompt)) 中,int 正在为我们处理转换和验证。一旦我们创建了整数n,我们就可以继续验证n 是一个非负整数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-13
      • 2017-05-08
      • 2013-05-11
      • 2022-11-14
      • 2016-08-07
      • 2021-05-15
      相关资源
      最近更新 更多