3

我正在学习 Python,我发现了一些关于 Python 如何构造一个让我感到困惑的子类的东西。

我有一个从列表类继承的类,如下所示。

class foo(list):
    def __init__(self, a_bar):
        list.__init__([])
        self.bar = a_bar

我知道那list.__init__([])需要在那里,但我对此感到困惑。在我看来,这条线只会创建一个新的列表对象,然后将其分配给任何内容,所以我怀疑它只会被垃圾收集。Python 怎么知道这个列表是我的对象的一部分?我怀疑幕后发生了一些事情,我想知道它是什么。

4

4 回答 4

3

多重继承安全的做法是:

class foo(list):
    def __init__(self, a_bar):
        super(foo, self).__init__()
        ...

这可能更清楚地表明您正在调用基类ctor。

于 2012-07-28T18:26:54.210 回答
2

您通常在子类化和覆盖__init__()函数时这样做:

list.__init__(self)

如果您使用的是 Python 3,则可以使用super()

super().__init__()
于 2012-07-28T18:24:40.977 回答
1

实际对象不是使用创建的,__init__而是使用创建的__new____init__不是用于创建对象本身,而是用于初始化它——即添加属性等。在__init__调用时,__new__已经调用了,因此在您的示例中,列表甚至在您的代码运行之前就已经创建了。 __init__不应该返回任何东西,因为它应该“就地”初始化对象(通过改变它),所以它会产生副作用。(请参阅上一个问题文档。)

于 2012-07-28T18:24:40.267 回答
1

你说对了一部分:

list.__init__([]) 

“创建一个新的列表对象。” 但是这段代码是错误的。正确的代码_should_be:

list.__init__(self)

你需要它存在的原因是因为你继承自一个list有它自己的方法的__init__()方法,它(大概)对初始化本身很重要。当您定义自己的__init__()方法时,您实际上是在覆盖继承的同名方法。为了确保父类的__init__()代码也被执行,您需要调用该父类的__init__().

有几种方法可以做到这一点:

#explicitly calling the __init__() of a specific class
#"list"--in this case
list.__init__(self, *args, **kwargs)     

#a little more flexible. If you change the parent class, this doesn't need to change
super(foo, self).__init__(*args, **kwargs) 

有关super()查看此问题的更多信息,有关超级陷阱的指导,请参阅本文

于 2012-07-28T20:14:16.450 回答