Reputation: 2563
I want to create a child class from a parent class. This is to reduce redundancy in code. For instance,
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
I don't want to pass parameters again and again for all child classes. Is there a way I could make Child1 and Child2 from Parent class?
I have 30+ parameters and many child classes. It seems very redundant to write out all parameters. Plus, they all share the same parameters as parents.
Upvotes: 3
Views: 10098
Reputation: 365617
What you're looking to do here has nothing to do with instantiation. That word means to create an instance of a class. You can't "instantiate a child class from parent class", because a class object is not (except in very unusual circumstances) an instance of its base class.
What you're trying to do is to eliminate some boilerplate.
Python is very flexible—instances can define attributes wherever they want, classes can have any signature they want for methods like __init__
and __repr__
, etc. This is very powerful, but it also means that when you have a very repetitive class hierarchy, you have to repeat yourself a lot. But—because Python is very flexible—you can write tools to generate all that repetitive stuff for you, or you can just use tools that come with the language, like @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
That's all it takes to define your classes, including automatically generating __init__
methods that can handle both positional and keyword arguments and forward the right things to base classes, and __repr__
methods that display things in some useful way, and static type hints that Mypy can check for you, and so on, without any repetition:
>>> 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
If you read the docs, you'll see that there's a lot more flexibility there (and even more in attrs
), but the defaults give you what you want 80% of the time.
@dataclass
was added in Python 3.7. There's a backport for 3.6 that you can install with just pip install dataclasses
, but if you need to work with 3.5 or 2.7, you'll need a third-party library like attrs
instead. Also look at namedtuple
for very simple cases, which works all the way back to 2.6 and 3.1.
Upvotes: 4
Reputation: 87054
It's not clear from your example whether inheritance is appropriate here. Does the child satisfy the is a relationship, i.e., is the child really a subclass of the parent? If it does not then you should consider using composition rather than inheritance.
I suggest composition because you mention, in a comment, instantiating the parent class and using that instance in the "child" classes. So you could create an instance of the parent and pass it to __init__()
of the "child" classes, thereby using composition.
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
Within the child classes you would access parent attributes via self.parent.a
for example.
Upvotes: 3
Reputation: 57033
You can pass all parameters to the subclass's __init__
as a list, pass as many as necessary to the superclass, and use the rest in the subclass itself:
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>
Upvotes: 0