【问题标题】:Exception handling is ignored with try-except around a function definition在函数定义周围使用 try-except 忽略异常处理
【发布时间】:2019-10-10 23:47:53
【问题描述】:

我的消息“除以 0 错误”没有通过,而是收到了正常的 ZeroDivisionError。

#!/usr/bin/python

t = raw_input("do you want to play a game?[y/n]" )

#r = raw_input("Please enter a number")

#e = raw_input("Please enter a number again")

try:
 def di (a, b):
  return  a/b
except ZeroDivisionError:
 print "Divide by 0 Error"

while t == "y":
  u = raw_input("Please enter / sign ")
  if u == "/":
   r = int(raw_input("Please enter a number"))
  try:
   e = int(raw_input("Please enter a number again"))
   print "the answer is", di(r, e)
   t = raw_input("do you want to play a game?[y/n]" )


  except ValueError:
   t = raw_input( "Invalid input, must be a number. Press yes to continue, no stop")

【问题讨论】:

  • 因为您将raise 与print 混淆了。如果要引发异常,请使用raise。不是print。 print 打印东西。 raise 引发异常。

标签: python python-2.7 exception


【解决方案1】:

更仔细地查看代码:

try:
    def di (a, b):
        return  a/b

except ZeroDivisionError:
    print "Divide by 0 Error"

您的try/except 块包含整个函数定义:它专门用于定义函数。当函数从调用中执行时,没有异常块处于活动状态。

改用这个:

def di (a, b):
    try:
        return  a/b
    except ZeroDivisionError:
        print "Divide by 0 Error"

【讨论】:

  • 当你达成一个决议时,请记得给有用的答案投票并接受最好的答案(即使你必须自己写)。这允许 Stack Overflow 归档您的问题。非常感谢,无论我是否获得声誉。
【解决方案2】:

我对这个问题的看法(显然很有趣,足以引发多个答案,做得好)是记住,在 Python 中,类和函数定义像大多数其他语句一样执行。

try:
    def di (a, b):
        return  a/b
except ZeroDivisionError:
    print "Divide by 0 Error"

说:

“尝试定义一个名为 di 的函数,该函数返回其参数的被除数。如果定义该函数引发 ZeroDivisionError 异常,则打印一条解释性消息。”不会引发异常。

我怀疑需要的是:

“定义一个试图返回其参数被除数的函数。如果除法引发ZeriDivisionError 异常,该函数将打印一条解释性消息并返回None。”所以def应该围绕整个函数的逻辑:

def di(a, b):
    try:
        return a/b
    except ZeroDivisionError:
        print "Divide by 0 error"

作为一个更一般的程序设计点,这样的函数有点耦合不良。 Python 程序员可能会得出结论,除非受到其他因素的限制,否则不捕获异常会更简单:大概调用者当前必须测试None 以确定是否发生异常,那么为什么不直接在异常发生的地方捕获异常呢?必须要处理,在那里处理?

通过返回不同类型的对象来指示数据的无效性会导致代码复杂且难以阅读,从长远来看,最好避免使用。不过,对于学习练习来说完全可以接受!

【讨论】:

    【解决方案3】:

    TLDR:将异常处理程序移到实际发生异常的函数中:

    def di(a, b):
        try:
            return a/b
        except ZeroDivisionError:
            print("Divide by 0 Error")
    

    Python 中的函数定义会被执行,而这种执行可能会产生副作用——例如修改对象或引发异常。但是,根据定义,只有函数签名会立即运行;主体被存储并且仅在函数被调用时运行。

    >>> def func(arg=print("default evaluated")):
    ...     print("body evaluated")
    ...
    default evaluated
    >>> func
    <function __main__.func(arg=None)>
    >>> func()
    body evaluated
    

    当您在异常处理程序中定义函数时,此异常处理程序仅接收评估签名时引发的异常。例如,计算默认参数可能会引发ZeroDivisionError:

    >>> def invalid_def(arg=10/0):
    ...     pass
    ...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ZeroDivisionError: division by zero
    

    这种情况下的异常处理程序很少是您想要的。有条件地定义一个函数可能很有用,例如如果NameError 表示依赖项不可用。

    通常您希望处理源自函数体的异常。每当实际调用函数时,都会引发这些:

    >>> def invalid_call():
    ...     return 10 / 0
    ...
    >>> invalid_call()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in invalid_call
    ZeroDivisionError: division by zero
    >>> invalid_call()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in invalid_call
    ZeroDivisionError: division by zero
    

    有两种方法可以处理此类异常:外部或内部。

    • 外部处理需要在每个调用站点有一个异常处理程序。这更灵活,但需要样板文件,因为每次调用都需要一个异常处理程序。

      >>> try:
      ...     invalid_call()
      ... except ZeroDivisionError:
      ...     print("suppressed an external error")
      
    • 内部处理需要主体中的异常处理程序。这不太灵活,但不需要样板,因为一个异常处理程序涵盖所有情况。

      >>> def valid_call():
      ...     try:
      ...         return 10 / 0
      ...     except ZeroDivisionError:
      ...         print("suppressed an internal error")
      

    这两种方法都有效;选择哪个取决于您是否更需要可用性或可重用性。值得注意的是,将这两种方法结合起来并不少见:内部处理程序泛化异常,而外部处理程序只期望一般异常。

    例如,在您的情况下,这将允许处理多个操作:

    def div(a, b):
        try:
            return  a / b
        # convert operation-specific exception to general one
        except ZeroDivisionError:
            raise ValueError("Cannot divide by 0")
    
    # may be another operation -- add, mul, sub, ...
    operation = div
    
    try:
        operation(10, 0)
    # only handle exception general to all operations
    except ValueError as err:
        print("Invalid values: %s" % err)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-03
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 2020-10-27
      • 2015-09-10
      • 2017-05-20
      相关资源
      最近更新 更多