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

Python: Is it bad form to raise exceptions within __init__?

__init__内提出例外是否被认为是不好的形式?如果是这样,那么当某些类变量初始化为None或类型不正确时,抛出错误的公认方法是什么?


__init__()中提出例外是完全可以的。没有其他好的方法来指示构造函数中的错误条件,并且在标准库中有数百个示例,在标准库中构建对象可以引发异常。

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


确实,指示构造函数中错误的唯一正确方法是引发异常。这就是为什么在C++和其他面向对象语言中,已经设计了异常安全的思想,如果在对象的构造函数中抛出异常(不意味着对象的初始化是不完整的),则不调用析构函数。在脚本语言(如Python)中,情况往往不是这样。例如,如果套接字连接()失败,下面的代码会引发AtEdTrError错误:

1
2
3
4
5
6
7
8
9
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开发人员避免完全使用析构函数,但这是另一个争论的问题。


我看不出有什么理由认为它的形式不好。

相反,与返回错误代码相反,异常的一个原因是构造函数通常不能返回错误代码。因此,至少在C++语言中,提高异常是唯一的方法来发出错误信号。


标准图书馆说:

1
2
3
4
>>> 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'

我也不明白为什么它会被认为是不好的形式。


我认为这是内置ValueError异常的最佳情况。


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


我同意上述所有观点。

实际上,除了引发异常之外,没有其他方法可以表明在初始化对象时发生了错误。

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

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