版权声明:转载 或者复制请标注来源 https://blog.csdn.net/qq_34979346/article/details/83240137
1.如果重写了父类的方法,还有没有必要使用父类的方法。
看下边的例子,简单介绍调用父类的方法。
class A:
def said(self):
print("A")
class B(A):
def said(self):
print("B")
super().said()
b=B()
b.said()
#打印结果
B
A
上边的例子既然重写了父类的方法, 为什么还要调用super?
上边的例子是没有必要调用父类,但是下边的情况是有必要的,你做下比较。
from threading import Thread
class Mytread(Thread):
def __init__(self,name,user):
self.user=user
super().__init__(name=name) #调用了父类的name 的属性
这样的好处简单的介绍下,复用父类的name 属性,就不必添加对name属性添加额外的代码,因为父类已经实现了。 看下 父类属性的代码如下:
def __init__(self, group=None, target=None, name=None,args=(), kwargs=None, *, daemon=None):
assert group is None, "group argument must be None for now"
if kwargs is None:
kwargs = {}
self._target = target
self._name = str(name or _newname())
self._args = args
self._kwargs = kwargs
if daemon is not None:
self._daemonic = daemon
else:
self._daemonic = current_thread().daemon
self._ident = None
self._tstate_lock = None
self._started = Event()
self._is_stopped = False
self._initialized = True
# sys.stderr is not stored in the class like
# sys.exc_info since it can be changed between instances
self._stderr = _sys.stderr
# For debugging and _after_fork()
_dangling.add(self)
总结:如果不是完全覆盖父类函数,重构函数要复用父类的部分属性。 如果父类完全可以替代子类的构造函数,就没有必要重写父类方法,全部用父类的方法。 和父类的方法没有联系是子类独特的特性,需要自己添加属于子类自己的构造函数 或者属性。
2.当存在多继承的时候,读取父类的顺序是什么样呢?
前面我们也介绍了当有多重继承的时候,读取方法和属性用的MRO 读取顺序,但是有了super的时候就变得更复杂了,一定要注意,否则读取的父类就乱套,先看下这个例子。
class A:
def __init__(self):
print("A")
class B(A): #继承父类A
def __init__(self):
print("B")
super().__init__() #调用父类的 init
class C(A): #继承父类A
def __init__(self):
print("C")
super().__init__() #调用父类的 init
class D(B,C): #继承父类B,C
def __init__(self):
print("D")
super().__init__() #调用父类的 init
d=D()
#打印结果是
D
B
C
A
大家一定有疑问,为什么 从B 不直接读取B 的父类A 呢, 直接 去读C 了呢 ?
答案是: 多重继承关系都有优先级的,也是我们经常介绍的 MRO 读取路径,python有自省机制可以用MRO函数查到他的路径,我们一起看看吧。
print(D.__mro__)
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
由于D 同时继承了B和C ,由于B 在前面 优先级高于C , 所以MRO 路线是 D>B>C>A 正好跟我们打印的顺序一样。
这也解决我们的题目的疑问。