为什么 super().__init__ () 在 Derived class in Python 中的行为与 super().override() 不同?
Why does super().__init__ () behave differently from super().override() in the Derived class in Python?
我想知道为什么 self.name 是 'abc' 而 super().__init__('abc' ) 被调用,但在调用 super().override() 时变为 'Nicky'?
是不是因为调用super().__init__('abc')时Derived实例还没有创建,所以Baseclass的属性是改用了?
class Base():
def __init__(self, name):
self.name = name
self.base = 'base class'
print('Base', self.name)
def override(self):
print('Base-override', self.name)
class Derived(Base):
def __init__(self, name, age):
super().__init__('abc')
self.name = name
self.age = age
def override(self):
super().override()
d = Derived('Nicky', 20) # Base abc
d.override() # Base-override Nicky
没什么神秘的。
您正在使用 name = 'abc
创建基础 class,然后使用 'Nicky' 覆盖 sef.name
。
从这段代码可以看出:
super().__init__('abc')
self.name = name
self.age = age
为了执行 self.name = name
,必须完成表达式 super().__init__('abc')
。
如果你加更多的打印,你会更好地理解它
class Base():
def __init__(self, name):
print('Base1', self.__dict__)
self.name = name
self.base = 'base class'
print('Base2', self.name, self.__dict__)
def override(self):
print('Base-override', self.name)
class Derived(Base):
def __init__(self, name, age):
print('Derived1', self.__dict__)
super().__init__('abc')
self.name = name
self.age = age
print('Derived2', self.name, self.__dict__)
def override(self):
super().override()
d = Derived('Nicky', 20) # Base abc
d.override() # Base-override Nicky
输出
Derived1 {}
Base1 {}
Base2 abc {'name': 'abc', 'base': 'base class'}
Derived2 Nicky {'name': 'Nicky', 'base': 'base class', 'age': 20}
Base-override Nicky
你的objectd
的属性name
没有不同的版本,都指的是同一个值,不要误以为name
是parent 和 child class 之间的区别,毕竟,它只是相同的 object,与 class 层次结构无关。
这只是你在某个时间点最后设置的问题。在这里,当你调用 super().__init__('abc')
时,你还没有在你的 Derived.__init__()
中初始化名称“Nicky”,因此你首先看到了“abc”的值。
这与执行顺序以及您如何使用参数有关。 class 是数据的集合,并且具有一些处理该数据的函数。您可以使用 super()
从父 class.
显式调用实现
作为方法的 __init__
或作为属性的 name
没有什么特别之处。您的调用顺序如下:
Derived('Nicky', 20)
使用 object.__new__
创建一个新的空对象,然后调用 Derived.__init__(obj, 'Nicky', 20)
。请记住,此时属性字典为空。
Derived.__init__(obj, 'Nicky', 20)
通过 super()
. 调用 Base.__init__(obj, 'abc')
开始
Base.__init__(obj, 'abc')
将 obj.name
设置为 'abc'
,将 obj.base
设置为 'base class'
。然后 returns 将这两个属性设置在字典中。这是第一个 print
发生的地方。
Derived.__init__(obj, 'Nicky', 20)
然后运行并设置 obj.name
为 'Nicky'
,obj.age
为 20
。然后 returns。关键是 obj.name
与 Base.__init__
所研究的属性相同:不同的方法,相同的数据。
Derived('Nicky', 20)
returns 新创建和初始化的对象,您将其分配给名称 d
.
- 当您调用
d.override
或任何其他方法时,它可以访问 d.__dict__
,就像之前的方法留下的一样。
除了关于如何存储和传递实例数据的课程之外,这是关于如何设计初始化程序的课程。通常,您调用 super
是为了避免在派生的 class 中做不必要的工作。在 __init__
中,这意味着让基 class 处理名称信息。这也意味着当前实现的 override
不应该存在:无论如何都会在派生实例上调用基本实现,如果这就是您所做的全部,您实际上不需要覆盖它:
class Base():
def __init__(self, name):
self.name = name
self.base = 'base class'
print('Base', type(self), self.name)
def override(self):
print('Base-override', type(self), self.name)
class Derived(Base):
def __init__(self, name, age):
super().__init__(name)
self.age = age
我已将 type(self)
添加到您的打印输出中,因此您可以看到它是 Derived
的一个实例,当您实例化 Derived
时调用 Base
方法。
我想知道为什么 self.name 是 'abc' 而 super().__init__('abc' ) 被调用,但在调用 super().override() 时变为 'Nicky'?
是不是因为调用super().__init__('abc')时Derived实例还没有创建,所以Baseclass的属性是改用了?
class Base():
def __init__(self, name):
self.name = name
self.base = 'base class'
print('Base', self.name)
def override(self):
print('Base-override', self.name)
class Derived(Base):
def __init__(self, name, age):
super().__init__('abc')
self.name = name
self.age = age
def override(self):
super().override()
d = Derived('Nicky', 20) # Base abc
d.override() # Base-override Nicky
没什么神秘的。
您正在使用 name = 'abc
创建基础 class,然后使用 'Nicky' 覆盖 sef.name
。
从这段代码可以看出:
super().__init__('abc')
self.name = name
self.age = age
为了执行 self.name = name
,必须完成表达式 super().__init__('abc')
。
如果你加更多的打印,你会更好地理解它
class Base():
def __init__(self, name):
print('Base1', self.__dict__)
self.name = name
self.base = 'base class'
print('Base2', self.name, self.__dict__)
def override(self):
print('Base-override', self.name)
class Derived(Base):
def __init__(self, name, age):
print('Derived1', self.__dict__)
super().__init__('abc')
self.name = name
self.age = age
print('Derived2', self.name, self.__dict__)
def override(self):
super().override()
d = Derived('Nicky', 20) # Base abc
d.override() # Base-override Nicky
输出
Derived1 {}
Base1 {}
Base2 abc {'name': 'abc', 'base': 'base class'}
Derived2 Nicky {'name': 'Nicky', 'base': 'base class', 'age': 20}
Base-override Nicky
你的objectd
的属性name
没有不同的版本,都指的是同一个值,不要误以为name
是parent 和 child class 之间的区别,毕竟,它只是相同的 object,与 class 层次结构无关。
这只是你在某个时间点最后设置的问题。在这里,当你调用 super().__init__('abc')
时,你还没有在你的 Derived.__init__()
中初始化名称“Nicky”,因此你首先看到了“abc”的值。
这与执行顺序以及您如何使用参数有关。 class 是数据的集合,并且具有一些处理该数据的函数。您可以使用 super()
从父 class.
作为方法的 __init__
或作为属性的 name
没有什么特别之处。您的调用顺序如下:
Derived('Nicky', 20)
使用object.__new__
创建一个新的空对象,然后调用Derived.__init__(obj, 'Nicky', 20)
。请记住,此时属性字典为空。Derived.__init__(obj, 'Nicky', 20)
通过super()
. 调用 Base.__init__(obj, 'abc')
将obj.name
设置为'abc'
,将obj.base
设置为'base class'
。然后 returns 将这两个属性设置在字典中。这是第一个print
发生的地方。Derived.__init__(obj, 'Nicky', 20)
然后运行并设置obj.name
为'Nicky'
,obj.age
为20
。然后 returns。关键是obj.name
与Base.__init__
所研究的属性相同:不同的方法,相同的数据。Derived('Nicky', 20)
returns 新创建和初始化的对象,您将其分配给名称d
.- 当您调用
d.override
或任何其他方法时,它可以访问d.__dict__
,就像之前的方法留下的一样。
Base.__init__(obj, 'abc')
开始
除了关于如何存储和传递实例数据的课程之外,这是关于如何设计初始化程序的课程。通常,您调用 super
是为了避免在派生的 class 中做不必要的工作。在 __init__
中,这意味着让基 class 处理名称信息。这也意味着当前实现的 override
不应该存在:无论如何都会在派生实例上调用基本实现,如果这就是您所做的全部,您实际上不需要覆盖它:
class Base():
def __init__(self, name):
self.name = name
self.base = 'base class'
print('Base', type(self), self.name)
def override(self):
print('Base-override', type(self), self.name)
class Derived(Base):
def __init__(self, name, age):
super().__init__(name)
self.age = age
我已将 type(self)
添加到您的打印输出中,因此您可以看到它是 Derived
的一个实例,当您实例化 Derived
时调用 Base
方法。