正在初始化 parent class 实例属性

Initializing parent class instance attributes

我了解如何初始化 parent class 以在 child class 中获取它们的实例属性,但不完全了解幕后发生的事情这个。 (注意:这里不是故意使用 super,只是为了说明清楚)

下面我们通过向 child class B 添加一个额外的属性 y 来扩展 class A。如果在实例化 b=B() 之后查看 class 字典,我们会正确地看到 b.x(继承自 class A)和 b.y

我假设在高层次上这是通过调用 A.__init__(self,x=10) 执行类似于 b.x=10 的操作(正常实例属性的分配方式)在 __init__ 中完成的class B 个。我有点不清楚,因为您正在调用 class A__init__,而不是 class B,但 class B 仍然会相应地更新它的实例属性。 class A's __init__ 如何知道更新 b's 实例属性。

这与继承方法不同,后者 b object 在其特定命名空间中没有显式继承方法,但会在调用缺失方法时查找继承链。使用该属性,该方法实际上位于 b 的命名空间中(它是实例字典)。

  class A:
        def __init__(self,x):
            self.x = x

    class B(A):
        def __init__(self):
            A.__init__(self,x=10)
            self.y = 1 

    b = B() 
    print(b.__dict__) 
    >>>{x:10,y:1} #x added to instance dict from parent init

下面我们继承自built-in列表。在这里,与上面类似,因为我们在 Foolist 的 __init__ 中调用列表的 __init__ 方法,我希望看到一个包含元素的实例字典,但它无处可寻。值 123 在 object 某处,可以通过打印 alist 看出,但不在实例字典中。

class Foolist(list):
    def __init__(self, elems):
        list.__init__(self, elems)

alist = Foolist('123')

那么当从 child 的 __init__ 调用 parent 的 __init__ 时,继承 class 到底发生了什么?值是如何绑定的?它似乎与方法查找不同,因为您不是按需搜索继承链,而是实际为继承 class 的实例字典赋值。

调用 parents init 是如何填充它的 child 的实例字典的?为什么 Foolist 示例不这样做?

答案很简单:self

作为一个非常粗略的概述,当实例化一个 class 时,一个对象 被创建。这或多或少从字面上看只是一个没有任何附属关系的空容器。*然后这个 "empty container" 被传递给正在实例化的 class 的 __init__ 方法,在那里它变成.. . self 论点!然后,您将在该对象上设置一个属性。然后,您将调用另一个 class 的 __init__ 方法, 明确地将您的特定 self 对象传递给该方法;该方法然后将另一个属性添加到对象。

这实际上是每个实例方法的工作原理。每个方法隐式接收 "current object" 作为其第一个参数 self。调用父项的 __init__ 方法时,实际上是在使该对象的传递非常明确。

您可以用这个简单的例子来模拟该行为:

def init_a(obj):
    obj.x = 10

def init_b(obj):
    init_a(obj)
    obj.y = 20

o = {}
init_b(o)

* 对象不完全是 "empty",对象上设置了特定的属性,这些属性与特定的 class 建立了从属关系,因此对象是 "an instance of" 某个 class,而Python可以根据需要定位它从class继承的所有方法。