簡體   English   中英

如何從父類實例化子類

[英]How to instantiate a child class from parent class

我想從父類創建子類。 這是為了減少代碼中的冗余。 例如,

class Parent():
   def __init__(self, a, b, c, d, e, f, g):
       self.a = a
       self.b = b
       ...
       self.g = g

class Child1(Parent):
   def __init__(self, a, b, c, d, e, f, g, h, i, j, k):
          super().__init__(a, b, c d, e, f, g)
          self.i = i
          self.j = j
          self.k = k

class Child2(Parent):
   def __init__(self, a, b, c, d, e, f, g, h, x, y, z):
          super().__init__(a, b, c d, e, f, g)
          self.x = x
          self.y = y
          self.z = z

我不想為所有子類一次又一次地傳遞參數。 有什么方法可以使我從Parent類中獲得Child1和Child2嗎?

我有30多個參數和許多子類。 寫出所有參數似乎很多余。 另外,它們都與父母共享相同的參數。

您要在此處執行的操作與實例化無關。 這個詞的意思是創建一個類的實例。 您不能“實例化父類的子類”,因為類對象不是(除非在非常特殊的情況下)其基類的實例。

您正在嘗試做的是消除一些樣板。

Python非常靈活-實例可以在所需的任何地方定義屬性,類可以對__init____repr__等方法具有所需的任何簽名。這非常強大,但是這也意味着當您具有非常重復的類層次結構時,重復很多 但是,由於Python非常靈活,因此您可以編寫工具來為您生成所有重復的內容,也可以只使用該語言@dataclass工具,例如@dataclass1

from dataclasses import dataclass

@dataclass
class Parent:
    a: int
    b: int
    c: int
    d: int
    e: int
    f: int
    g: int
    h: int

@dataclass
class Child1(Parent):
    i: int
    j: int
    k: int

@dataclass
class Child2(Parent):
    x: int
    y: int
    z: int

這一切都需要來定義類,包括自動生成__init__ ,可以同時處理位置和關鍵字參數和轉發正確的事情的基礎類的方法,並__repr__在一些有用的方式展示事物的方法,和靜態類型暗示Mypy可以檢查為您服務,依此類推,無需重復:

>>> c1 = Child1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
>>> c1
Child1(a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9, j=10, k=11)
>>> c1b = Child1(1, 2, 3, 4, 5, 6, 7, k=11, j=10, h=8, i=9)
>>> c1 == c1b
True
>>> c2 = Child2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
>>> c1 == c2
False

如果您閱讀這些文檔,就會發現那里有更多的靈活性( attrs甚至更多),但是默認值在80%的時間給了您想要的東西。


@dataclass是在Python 3.7中添加的。 一個3.6版本的反向端口 ,您可以僅使用pip install dataclasses ,但是如果您需要使用3.5或2.7版本,則需要一個類似attrs的第三方庫。 還可以查看namedtuple中非常簡單的情況,該情況一直可以追溯到2.6和3.1。

您可以將所有參數作為列表傳遞給子類的__init__ ,將盡可能多的參數傳遞給超類,並在子類本身中使用其余參數:

class Parent():
    def __init__(self,a,b,c):
        print(a,b,c)

class Child1(Parent):
    def __init__(self, *args):
        super().__init__(*args[:3]) # 3 for the parent
        self.x, self.y = args[3:] # 2 for myself
        print(self.x, self.y)

Child1(1,2,3,4,5)
#1 2 3
#4 5
#<__main__.Child1 object at 0x7f5d70c3c9e8>

從您的示例尚不清楚繼承在這里是否合適。 孩子是否滿足是一種關系,即是孩子真正的父母的一個子類? 如果不是,那么您應該考慮使用組合而不是繼承。

我建議使用組合,因為您在注釋中提到了實例化父類並在“子”類中使用該實例 因此,您可以創建父級實例並將其傳遞給“子級”類的__init__() ,從而使用組合。

class Parent():
   def __init__(self, a, b, c, d, e, f, g):
       self.a = a
       self.b = b
       ...
       self.g = g

class Child1:
    def __init__(self, parent, h, i, j, k):
        self.parent = parent
        self.h = h
        self.i = i
        self.j = j
        self.k = k

在子類中,您將通過例如self.parent.a訪問父屬性。

暫無
暫無

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

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