简体   繁体   English

Python继承和__init__

[英]Python Inheritance and __init__

I'm learning Python and I've found something about how Python constructs a sub class which confuses me. 我正在学习Python,我发现了一些关于Python如何构造一个令我困惑的子类的东西。

I have a class that inherits from the list class as follows. 我有一个继承自列表类的类,如下所示。

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

I know that list.__init__([]) needs to be there but I'm confused about it. 我知道list.__init__([])需要在那里,但我对此感到困惑。 It seems to me that this line will just create a new list object and then assign it to nothing, so I would suspect that it would just get garbage collected. 在我看来,这一行只会创建一个新的列表对象,然后将其分配给任何东西,所以我怀疑它只会被垃圾收集。 How does Python know that this list is part of my object? Python如何知道这个列表是我的对象的一部分? I suspect that there is something happening behind the scenes and I'd like to know what it is. 我怀疑幕后发生了一些事情,我想知道它是什么。

The multiple-inheritance-safe way of doing it is: 这种多继承安全的方法是:

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

which, perhaps, makes it clearer that you're calling the baseclass ctor. 这或许可以让你更清楚你正在调用基类ctor。

You usually do this when subclassing and overriding the __init__() function: 通常在子类化和覆盖__init__()函数时执行此操作:

list.__init__(self)

If you're using Python 3, you can make use of super() : 如果您使用的是Python 3,则可以使用super()

super().__init__()

You're partly right: 你是部分正确的:

list.__init__([]) 

"creates a new list object." “创建一个新的列表对象。” But this code is wrong. 但是这段代码错了。 The correct code _should_be: 正确的代码_should_be:

list.__init__(self)

The reason you need it to be there is because you're inheriting from a list that has it's own __init__() method where it (presumably) does important to initialize itself. 你需要它的原因有,因为你是从继承list有它自己的__init__()方法来初始化自己的地方(大概)确实很重要。 When you define your own __init__() method, you're effectively overriding the inherited method of the same name. 当您定义自己的__init__()方法时,您实际上会覆盖同名的继承方法。 In order to make sure that the parent class's __init__() code is executed as well, you need to call that parent class's __init__() . 为了确保父类的__init__()代码也被执行,您需要调用该父类的__init__()

There are several ways of doing this: 有几种方法可以做到这一点:

#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) 

For more on super() see this question , for guidance on the pitfalls of super, see this article . 有关super()更多信息,请参阅此问题 ,有关超级陷阱的指导,请参阅此文章

The actual object is not created with __init__ but with __new__ . 实际对象不是使用__init__创建的,而是使用__new__创建的。 __init__ is not for creating the object itself but for initializing it --- that is, adding attributes, etc. By the time __init__ is called, __new__ has already been called, so in your example the list was already created before your code even runs. __init__不是用于创建对象本身,而是用于初始化它 - 即添加属性等。当__init__被调用时, __init__ __new__已被调用,因此在您的示例中,列表已经在您的代码运行之前创建。 __init__ shouldn't return anything because it's supposed to initialize the object "in-place" (by mutating it), so it works by side-effects. __init__不应返回任何内容,因为它应该“就地”初始化对象(通过改变它),因此它通过副作用起作用。 (See a previous question and the documentation .) (参见上一个问题文档 。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM