【问题标题】:Implementation of `Exception.__str__()` in Python`Exception.__str__()` 在 Python 中的实现
【发布时间】:2016-07-21 09:21:55
【问题描述】:

我从来没有完全理解 Python(或者说实话)中的异常处理。我正在尝试自定义异常,并发现了以下行为。

class MyError(Exception):
    def __init__(self, anything):
        pass

me = MyError("iiiiii")
print(me)

输出:

iiiiii

我假设print() 调用Exception.__str__()

基类Exception如何知道打印iiiiii?字符串"iiiiii" 通过参数anything 传递给MyError 的构造函数,但anything 根本没有存储在MyError 中的任何位置!

此外,MyError 的构造函数不会调用其超类(异常)的构造函数。那么,print(me) 是如何打印出iiiiii 的呢?

【问题讨论】:

  • 什么版本的 Python?这无法在 Python 2.7 中重现。
  • 抱歉忘了说,Python 3.5.1。

标签: python python-3.x exception


【解决方案1】:

在 Python 3 中,BaseException 类有一个 __new__ 方法,将参数存储在 self.args 中:

>>> me.args
('iiiiii',)

您没有覆盖 __new__ 方法,只是覆盖了 __init__。您需要覆盖 both 以完全防止设置 self.args,因为两个实现都乐意设置该属性:

>>> class MyError(Exception):
...     def __new__(cls, *args, **kw):
...         return super().__new__(cls)  # ignoring args and kwargs!
...     def __init__(self, *args, **kw):
...         super().__init__()           # again ignoring args and kwargs
...
>>> me = MyError("iiiiii")
>>> me
MyError()
>>> print(me)

>>> me.args
()

在 Python 2 中,异常不会实现 __new__,并且您的示例不会打印任何内容。参见issue #1692335 了解为什么要添加__new__ 方法;基本上是为了避免像你这样__init__方法不调用super().__init__()的问题。

注意__init__ 不是构造函数;到那时,该实例已经由__new__ 构建。 __init__ 只是初始化器

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 2013-12-13
    • 2016-07-05
    相关资源
    最近更新 更多