Python:在__init__中引发异常是不好的形式?

时间:2009-10-01 23:47:39

标签: python exception

__init__内提出异常会被视为不良形式吗?如果是这样,那么当某些类变量初始化为None或类型不正确时,抛出错误的可接受方法是什么?

7 个答案:

答案 0 :(得分:133)

__init__()内提出异常绝对没问题。没有其他好方法可以在构造函数中指出错误条件,并且标准库中有数百个示例,其中构建对象可能引发异常。

当然,要提出的错误类由您决定。如果构造函数传递了无效参数,则ValueError最好。

答案 1 :(得分:22)

确实,在构造函数中指示错误的唯一正确方法是引发异常。这就是为什么在C ++和其他面向对象语言中考虑到异常安全性的原因,如果在对象的构造函数中抛出异常(意味着对象的初始化不完整),则不会调用析构函数。在脚本语言中通常不是这种情况,例如Python。例如,如果socket.connect()失败,则以下代码抛出AttributeError:

class NetworkInterface:
    def __init__(self, address)
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect(address)
        self.stream = self.socket.makefile()

    def __del__(self)
        self.stream.close()
        self.socket.close()

原因是在初始化流属性之前,在连接尝试失败后调用不完整对象的析构函数。你不应该避免从构造函数中抛出异常,我只是说在Python中编写完全异常安全的代码是很困难的。一些Python开发人员完全避免使用析构函数,但这是另一个争论的问题。

答案 2 :(得分:11)

我认为没有任何理由认为它应该是不好的形式。

相反,与返回错误代码相反,其中一个例外的事情就是知道,错误代码通常不能由构造函数返回。所以至少在像C ++这样的语言中,提出异常是发出错误信号的唯一方法。

答案 3 :(得分:5)

标准库说:

>>> f = file("notexisting.txt")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'notexisting.txt'

此外,我真的没有理由认为它应该被视为不良形式。

答案 4 :(得分:3)

我认为这是内置ValueError例外的完美案例。

答案 5 :(得分:2)

我同意上述所有内容。

除了引发异常之外,没有其他方法可以表明对象初始化时出现问题。

在大多数程序类中,类的状态完全依赖于该类的输入,我们可能会期望引发某种类型的ValueError或TypeError。

如果(例如)网络设备不可用或无法写入画布对象,则带有副作用的类(例如,具有网络或图形的类)可能会在init中引发错误。这对我来说听起来很明智,因为通常你想尽快了解失败情况。

答案 6 :(得分:2)

在某些情况下,从init中引发错误是不可避免的,但在init中做太多工作是一种糟糕的风格。您应该考虑创建工厂或伪工厂 - 一种返回设置对象的简单类方法。