如何从父类实例化子类

时间:2018-07-05 00:36:52

标签: python class inheritance

我想从父类创建子类。这是为了减少代码中的冗余。例如,

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多个参数和许多子类。写出所有参数似乎很多余。另外,它们都与父母共享相同的参数。

3 个答案:

答案 0 :(得分:1)

您要在此处执行的操作与实例化无关。这个词的意思是创建一个类的实例。您不能“实例化父类的子类”,因为类对象不是(除非在非常特殊的情况下)其基类的实例。

您想要做的是消除一些样板。

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中添加。您可以仅使用pip install dataclasses来安装a backport for 3.6,但是如果您需要使用3.5或2.7,则需要使用attrs之类的第三方库。另外,请查看namedtuple中非常简单的情况,该情况一直可以追溯到2.6和3.1。

答案 1 :(得分:0)

您可以将所有参数作为列表传递给子类的__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>

答案 2 :(得分:0)

从您的示例尚不清楚继承在这里是否合适。孩子是否满足is a关系,即孩子真的是父母的子类吗?如果没有,那么您应该考虑使用composition而不是继承。

我建议使用组合,因为您在注释中提到了实例化父类,并在“子”类中使用了该 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访问父属性。