簡體   English   中英

Python與super一起使用孫子繼承父級和子級

[英]Python using super with grandchild inheriting parent and child

[使用Python3.6]我有一個設計,其中孫子繼承了父級和子級(父級)。

class Parent:
    def aux_func(self):
        return "[parent aux]"

    def main_func(self):
        print("[parent main]" + self.aux_func())


class Child(Parent):
    def aux_func(self):
        return "[child aux]"

    def main_func(self):
        print("[child main]" + self.aux_func())


class Grandchild(Child, Parent):
    @classmethod
    def do_something(cls):
        g = Grandchild()
        g.main_func()
        super(Child, g).main_func()
        Parent.main_func(g)

Grandchild.do_something()

結果是-

[child main][child aux]
[parent main][child aux]
[parent main][child aux]

從Parent調用函數會使aux_func從Child類解析。 我試圖通過MRO流程,但是無法解釋從不同類調用的函數。 有人可以幫我嗎

  1. 為什么會這樣呢?
  2. 實現[parent main] [parent aux]的解決方法是什么?

您誤解了super()作用。 super()不會更改self引用的類型。 super(..., self).method()仍然會將self引用傳遞給要調用的方法,因此在所有三種情況下, self都是Grandchild()實例。

這意味着,在所有情況下, self.aux_func()按照正常的屬性解析順序,和Grandchild()的情況下, self.aux_func()總是會找到Child.aux_func和調用。

換句話說,唯一更改的查找是您在super()對象本身上查找的屬性。 如果需要更多此類更改,則需要再次使用super()或者需要為aux_func()函數的每個類賦予不同的名稱 一種實現方法是將方法設為私有

后者可以通過在函數的開頭(但不能在結尾處)用兩個下划線命名來完成。 然后在編譯時更改此類名稱,以在引用的所有位置注入類名稱:

class Parent:
    def __aux_func(self):
        # class private to Parent
        return "[parent aux]"

    def main_func(self):
        # any reference to __aux_func *in this class* will use
        # the Parent class-private version
        print("[parent main]" + self.__aux_func())


class Child(Parent):
    def __aux_func(self):
        # class private to Child
        return "[child aux]"

    def main_func(self):
        # any reference to __aux_func *in this class* will use
        # the Child class-private version
        print("[child main]" + self.__aux_func())

請參閱標識符保留類文檔

__*
類私有名稱。 當在類定義的上下文中使用時,此類別中的名稱將被重寫以使用變形的形式,以幫助避免基類和派生類的“私有”屬性之間的名稱沖突。

和“ 標識符(名稱)”部分

私有名稱修飾 :當在類定義中以文本形式出現的標識符以兩個或多個下划線字符開頭且不以兩個或多個下划線結尾時,則被視為該類的私有名稱。 在為專用名稱生成代碼之前,專用名稱會轉換為更長的格式。 轉換將在類名前面插入類名,並刪除前導下划線,並插入單個下划線。 例如,出現在名為Ham的類中的標識符__spam將轉換為_Ham__spam 此轉換獨立於使用標識符的句法上下文。

通過為__aux_func使用類私有命名,將在Parent定義的方法中__aux_func任何引用進行查找並找到_Parent__aux_func ,在Child對同名的任何引用將進行查找並查找_Child__aux_func 這兩個名稱是不同的,因此不會沖突:

>>> class Grandchild(Child, Parent):
...     @classmethod
...     def do_something(cls):
...         g = Grandchild()
...         g.main_func()
...         super(Child, g).main_func()
...         Parent.main_func(g)
...
>>> Grandchild.do_something()
[child main][child aux]
[parent main][parent aux]
[parent main][parent aux]

實現此目的的另一種方法是顯式使用不同的名稱。 說出parent_aux_func()child_aux_func() 類的私有名字真的只打算在這是為了通過第三方的代碼,而在子類可以使用什么名字太多的限制被繼承的API。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM