Super 你真的理解了吗?

版权声明:转载 或者复制请标注来源 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 正好跟我们打印的顺序一样。
这也解决我们的题目的疑问。

猜你喜欢

转载自blog.csdn.net/qq_34979346/article/details/83240137