Как создать экземпляр дочернего класса из родительского класса - PullRequest
0 голосов
/ 05 июля 2018

Я хочу создать дочерний класс из родительского класса. Это должно уменьшить избыточность в коде. Например,

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

Я не хочу передавать параметры снова и снова для всех дочерних классов. Есть ли способ сделать Child1 и Child2 из родительского класса?

У меня есть 30+ параметров и много дочерних классов. Кажется очень излишним выписывать все параметры. Кроме того, все они имеют те же параметры, что и родители.

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

Из вашего примера не ясно, уместно ли здесь наследование. Удовлетворяет ли ребенок отношение как , т. Е. Действительно ли ребенок является подклассом родителя? Если это не так, вам следует рассмотреть возможность использования композиции вместо наследования.

Я предлагаю состав, потому что вы упомянули в комментарии создание экземпляра родительского класса и использование этого instance в "дочерних" классах. Таким образом, вы можете создать экземпляр родительского элемента и передать его в __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.

0 голосов
/ 05 июля 2018

То, что вы ищете здесь, не имеет ничего общего с созданием экземпляра. Это слово означает создание экземпляра класса. Вы не можете "создать экземпляр дочернего класса из родительского класса", потому что объект класса не является (за исключением очень необычных обстоятельств) экземпляром его базового класса.

То, что вы пытаетесь сделать, это устранить какой-то шаблон.

Python очень гибок - экземпляры могут определять атрибуты там, где они хотят, классы могут иметь любую сигнатуру для таких методов, как __init__ и __repr__ и т. Д. Это очень мощно, но это также означает, что когда у вас есть очень повторяющаяся иерархия классов, вам приходится много повторяться. Но, поскольку Python очень гибок, вы можете написать инструменты для генерации всего этого повторяющегося материала или просто использовать инструменты, поставляемые с языком, например @dataclass: 1

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.

0 голосов
/ 05 июля 2018

Вы можете передать все параметры подклассу __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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...