python – 即使`__init __()`引发异常,也使用对象?

我遇到类__init__方法的一些微不足道的重要部分可能引发异常的情况.在这种情况下,我想显示错误消息,但继续使用实例.

一个非常基本的例子:

class something(object):
    def __init__(self):
        do_something_important()
        raise IrrelevantException()

    def do_something_useful(self):
        pass

try:
    that_thing = something()
except IrrelevantException:
    print("Something less important failed.")

that_thing.do_something_useful()

但是,最后一行不起作用,因为没有定义that_thing.奇怪的是,我可以发誓我以前做过这样的事情并且工作正常.我甚至想知道如何阻止人们使用这样一个未完成的实例,因为我发现即使出现错误也会创建它.现在我想使用它,它不起作用.嗯…?!?

PS:我自己写的东西,所以我控制着一切.

最佳答案 来自评论:

PS: something was written by myself, so I’m in control of everything.

那么,答案是显而易见的:只需删除那个引发IrrelevantException()

当然,您的真实代码可能没有引发IrrelevantException,而是调用可能引发的某些dangerous_function().但那没关系;你可以像在其他任何地方一样处理异常;你在__init__方法中的事实没有区别:

class something(object):
    def __init__(self):
        do_something_important()
        try:
            do_something_dangerous()
        except IrrelevantException as e:
            print(f'do_something_dangerous raised {e!r}')
        do_other_stuff_if_you_have_any()

这里的所有都是它的.你的__init__没有理由提出异常,因此首先不会出现如何处理异常的问题.

如果您无法修改某些内容,但可以将其子类化,那么您不需要任何花哨的东西:

class IrrelevantException(Exception):
    pass

def do_something_important():
    pass

class something(object):
    def __init__(self):
        do_something_important()
        raise IrrelevantException()

    def do_something_useful(self):
        pass

class betterthing(something):
    def __init__(self):
        try:
            super().__init__() # use 2.x style if you're on 2.x of course
        except IrrelevantException:
            pass # or log it, or whatever
        # You can even do extra stuff after the exception

that_thing = betterthing()
that_thing.do_something_useful()

现在do_something_important被调用,并且一个实例得到了我能够保存并且调用do_something_useful的返回,依此类推.正是你在寻找什么.

你当然可以用一些聪明的重命名技巧来隐藏一些东西:

_something = something
class something(_something):
    # same code as above

…或者只是使用包装器函数monkeypatch something .__ init__而不是包装类:

_init = something.__init__
def __init__(self):
    try:
        _init(self)
    except IrrelevantException:
        pass
something.__init__ = __init__

但是,除非有一个很好的理由让你无法明确表示你正在添加一个包装器,否则最好是明确的.

点赞