1. 程式人生 > >[Python]面向對象近期筆記-super

[Python]面向對象近期筆記-super

運行 調用父類 定義 允許 print 執行 init pytho between

Python面向對象高級

直接調用父類方法

class A:
    def __init__(self):
        print("hello")
class B(A):
    def __init__(self):
        A.__init__()

多繼承

class C(A,B):
    # ...
# 多繼承的查找循序是從左往右,註意繼承順序。
# 比如調用某個方法,A中也有B中也有,那麽默認就用的A的方法。

slots

class Student:
    __slots__ = ('name','age')
s = Student()
s.name = "ar" # 正確
s.score = 95 # 報錯,attribute err

slots限定只允許動態加name和age這兩個實例屬性。在子類中會繼承slots,子類自身定義slots的時候兩者取並集。

@property

property裝飾器用來解決反復調用麻煩的問題,簡化了函數調用。

# 直接抄例子了
# 不加裝飾器
class Student(object):

    def get_score(self):
         return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
        
 # 加裝飾器
class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
        
# 直接調用函數就可以檢驗

super

在pytorch和mxnet中繼承的時候都有這個東西,一探究竟。

# 舉個例子
class A:
  def __init__(self):
    print("Enter A")
    print("Leave A")
class B(A):
  def __init__(self):
    print("Enter B")
    super(B, self).__init__()
    print("Leave B")
class C(A):
  def __init__(self):
    print("Enter C")
    super(C, self).__init__()
    print("Leave C")
class D(A):
  def __init__(self):
    print("Enter D")
    super(D, self).__init__()
    print("Leave D")
class E(B, C, D):
  def __init__(self):
    print("Enter E")
    super(E, self).__init__()
    print("Leave E")
E()
'''
Enter E
Enter B
Enter C
Enter D
Enter A
Leave A
Leave D
Leave C
Leave B
Leave E
'''

首先我們要知道,python是解釋型語言,執行到哪裏就開始解釋然後得到結果,所以我們從程序運行處開始看。

  1. 實例化對象E,調用構造函數
  2. 輸出Enter E
  3. 開始調用父類init,調用B的init,輸出Enter B,發現要掉B的父類,super特殊就在這,要按照mro順序來調用,所以走到這裏要調B的父類A的init時,發現A之前還有CD沒有調用,那麽此時要去先調用CD的init
  4. 調用C的init,輸出Enter C,同樣的,發現A之前還有D
  5. 調用D的init,輸出Enter D,A之前沒有人了
  6. 調用A的init,輸出Enter A,輸出leave A
  7. 從D返回,輸出leave D
  8. ...

所以super的好處是,當多個類繼承自同一類的時候,調用父類函數的時候會有一個mro查找順序,以防止父類的函數被多次調用。至於mro,可以調用E.MRO()來查看。

[Python]面向對象近期筆記-super