在Python 3中,在调用super()之前重写父类属性

在Python 3中,在调用super()之前重写父类属性,python,class,python-3.x,inheritance,attributes,Python,Class,Python 3.x,Inheritance,Attributes,考虑下面的例子。Parent类有一个名为attr的属性。Child1和Child2都有一个同名属性。Child1和Child2之间的唯一区别在于Child1在覆盖父级的attr属性之前调用super()Child2似乎不会覆盖父级的attr,因为该属性是在super()调用之前定义的。在调用super() class Parent(): def __init__(self): self.attr = "parent" class Child1(Parent):

考虑下面的例子。
Parent
类有一个名为
attr
的属性。
Child1
Child2
都有一个同名属性。
Child1
Child2
之间的唯一区别在于
Child1
在覆盖父级的
attr
属性之前调用
super()
<相反,code>Child2似乎不会覆盖父级的
attr
,因为该属性是在
super()
调用之前定义的。在调用
super()

class Parent():

    def __init__(self):
        self.attr = "parent"

class Child1(Parent):

    def __init__(self):
        super().__init__()
        self.attr = "child1"

class Child2(Parent):

    def __init__(self):
        self.attr = "child2"
        super().__init__()

if __name__ == '__main__':
    child1 = Child1()
    print(child1.attr) # "child1"

    child2 = Child2()
    print(child2.attr) # "parent"
没有“家长的
attr
”和“孩子的
attr
”这样的东西。该实例上只有一个
attr
,无论它是从父类中的代码设置的,还是从子类中的代码设置的,还是从没有该类的代码设置的

换句话说,这些示例产生相同的结果:

例1 例2 例3 实际答案;) 因此,
Child1
Child2
之间的区别在于
Child1
\uuuu init\uuu
执行以下操作:

    self.attr = "parent"
    self.attr = "child1"
Child2
\uuuu init\uuuu
有效地做到了这一点:

    self.attr = "child2"
    self.attr = "parent"
没有“家长的
attr
”和“孩子的
attr
”这样的东西。该实例上只有一个
attr
,无论它是从父类中的代码设置的,还是从子类中的代码设置的,还是从没有该类的代码设置的

换句话说,这些示例产生相同的结果:

例1 例2 例3 实际答案;) 因此,
Child1
Child2
之间的区别在于
Child1
\uuuu init\uuu
执行以下操作:

    self.attr = "parent"
    self.attr = "child1"
Child2
\uuuu init\uuuu
有效地做到了这一点:

    self.attr = "child2"
    self.attr = "parent"
否。
super()。\uuuu init\uuuu()
是调用超类的
\uuuuuu init\uuuu
的缩写,将当前实例作为
self
传递给它

考虑一下创建
Child2
的实例时会发生什么。首先,创建该类的“裸”实例。必须初始化此实例。为此,Python将此实例作为
self
传递给
Child2.\uuu init\uu
。现在
Child2.\uuuu init\uuuu
首先向该实例添加一个
attr
属性。但是它接下来调用
super()。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。重要的是,
self
是我们正在初始化的
Child2
实例。因此
Parent.\uuuu init\uuuu
然后覆盖此实例的
attr
属性

通常,最好将
super()。\uuuu init\uuuu()
调用放在子类的
\uuuu init\uuu
中的第一位。这并不是一个真正的限制,大多数人都希望它能排在第一位

演示程序流程的示例:

class Parent(object):

    def __init__(self):
        print('Here I am, in the parent! My ID is: ' + str(id(self)))

class Child(Parent):

    def __init__(self):
        print('Initializing new Child instance with ID: ' + str(id(self)))
        super().__init__()
这样,创建
Child
的实例将打印出:

Initializing new Child instance with ID: 4372063120
Here I am, in the parent! My ID is: 4372063120
否。
super()。\uuuu init\uuuu()
是调用超类的
\uuuuuu init\uuuu
的缩写,将当前实例作为
self
传递给它

考虑一下创建
Child2
的实例时会发生什么。首先,创建该类的“裸”实例。必须初始化此实例。为此,Python将此实例作为
self
传递给
Child2.\uuu init\uu
。现在
Child2.\uuuu init\uuuu
首先向该实例添加一个
attr
属性。但是它接下来调用
super()。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。重要的是,
self
是我们正在初始化的
Child2
实例。因此
Parent.\uuuu init\uuuu
然后覆盖此实例的
attr
属性

通常,最好将
super()。\uuuu init\uuuu()
调用放在子类的
\uuuu init\uuu
中的第一位。这并不是一个真正的限制,大多数人都希望它能排在第一位

演示程序流程的示例:

class Parent(object):

    def __init__(self):
        print('Here I am, in the parent! My ID is: ' + str(id(self)))

class Child(Parent):

    def __init__(self):
        print('Initializing new Child instance with ID: ' + str(id(self)))
        super().__init__()
这样,创建
Child
的实例将打印出:

Initializing new Child instance with ID: 4372063120
Here I am, in the parent! My ID is: 4372063120