【问题标题】:Confused about try/except with custom Exception对 try/except 和自定义异常感到困惑
【发布时间】:2014-12-31 06:06:53
【问题描述】:

我的代码:

class AError(Exception):
    print 'error occur'
for i in range(3):
    try:
        print '---oo'
        raise AError
    except AError:
        print 'get AError'
    else:
        print 'going on'
    finally:
        print 'finally'

当我运行上面的代码时,输​​出是这样的:

error occur
---oo
get AError
finally
---oo
get AError
finally
---oo
get AError
finally

我认为字符串"error occur"应该出现3次,比如"---oo",但它只出现一次;为什么?

【问题讨论】:

    标签: python try-catch except


    【解决方案1】:

    为了澄清Paul's answer,这里有一个简单的例子:

    class Test(object):
    
        print "Class being defined"
    
        def __init__(self):
            print "Instance being created"
    
    
    for _ in range(3):
        t = Test()
    

    由此产生的输出将是:

    Class being defined
    Instance being created
    Instance being created
    Instance being created
    

    在class 定义内但在方法definition 之外的代码在定义类时只运行一次。

    如果您希望代码在创建实例时运行,它应该在__init__ 实例方法中(或者,偶尔在__new__ 类方法)。但是,请注意,如果您为子类定义__init__,您可能应该确保它也调用超类的__init__:

    class AError(Exception):
    
        def __init__(self, *args, **kwargs):
            Exception.__init__(self, *args, **kwargs) # call the superclass
            print 'error occur' # print your message
    

    这确保子类支持超类的参数;对于Exception,您可以例如传递错误信息:

    >>> raise AError("Something went wrong.")
    error occur # your message gets printed when the instance is created
    
    Traceback (most recent call last):
      File "<pyshell#11>", line 1, in <module>
        raise AError("Something went wrong.")
    AError: Something went wrong. # the error message passes through to the traceback
    

    有关*args, **kwargs 语法的解释,如果您不熟悉它,请参阅例如What does ** (double star) and * (star) do for parameters?。您也可以使用super 来调用超类方法,参见例如Understanding Python super() with __init__() methods.

    【讨论】:

    • 这个答案很清楚,我明白了。 3Q 非常好,你真好!
    【解决方案2】:

    'error occur' 只打印一次,用于整个班级。

    您可能希望它为所创建的类的每个实例运行。

    为此,请将其放入 __init__ 函数中,

    class AError(Exception):
        def __init__(self):
            print 'error occur'
    

    __init__ 在创建AError 的实例时被调用。

    【讨论】:

    • 您应该提到类定义和实例创建之间的区别,即为什么这会有所不同。此外,__init__ 应该接受参数并调用超类初始化程序,否则自定义错误将不支持,例如一条错误消息。
    • 我忘了类方法和实例方法的区别,3Q指点。
    【解决方案3】:

    我强烈建议不要在您的异常中放置任何打印语句,尤其是。不是他们的构造函数!例外是语义实体,如果需要,您可以将它们打印出来。如果您必须自动打印,请至少使用logging 或类似的包。

    您可能不知道的是,您可以像这样收集异常实例以在except 子句中使用:

    class MyError(Exception):
        pass
    
    for i in range(3):
        try:
            print '---oo'
            raise MyError("error msg no. {}".format(i))
            # Exception usually always accept a string as their first parameter
        except MyError, ex:
            # Exception instance available inside the except clause as `ex`
            print ex
        else:
            print 'going on'
        finally:
            print 'finally'
    

    【讨论】:

      【解决方案4】:

      'error occur' 字符串只出现一个,因为 Python 在解析您的 AError 类定义时会执行它。

      如果您希望每次创建类的实例时都执行它,则必须定义类的初始化器:

      class AError(Exception):
          def __init__(self):
              print 'error occur'
      
      for i in range(3):
          try:
              print '---oo'
              raise AError
          except AError:
              print 'get AError'
          else:
              print 'going on'
          finally:
              print 'finally'
      

      玩得开心(也许还可以阅读语言手册……)

      【讨论】:

      • 查看我的回答(以及我对 Paul 的评论) - AError.__init__ 应该调用 Exception.__init__ 并处理适当的参数。
      猜你喜欢
      • 2011-02-04
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多