1. 程式人生 > >Super 你真的理解了嗎?

Super 你真的理解了嗎?

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 正好跟我們列印的順序一樣。 這也解決我們的題目的疑問。