3

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.

asked Jul 5, 2018 at 0:36
9
  • Possible duplicate of Simple python inheritance Commented Jul 5, 2018 at 0:41
  • You must specify the parent class when defining a child class: Child1(Parent). Commented Jul 5, 2018 at 0:49
  • @DyZ ah yes that was a typo Commented Jul 5, 2018 at 0:53
  • 1
    If you have 30+ parameters, there must be something wrong with your code design. Have you considered passing a dictionary? Commented Jul 5, 2018 at 0:58
  • Well it's bunch of hyperparameters I need to tune for deep learning stuff... Commented Jul 5, 2018 at 1:04

3 Answers 3

4

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.

answered Jul 5, 2018 at 7:18
Sign up to request clarification or add additional context in comments.

Comments

3

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.

answered Jul 5, 2018 at 2:53

Comments

0

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>
answered Jul 5, 2018 at 0:45

2 Comments

i prefer not using *args for project specific reasons. It seems there is no way to instantiate a child from parent in python
@MoneyBall Is what you’re asking "How do I do the same thing as *args without using *args? If so, that’s not possible, but similar things are. For example, if you want a function that takes a fixed number of ages, but that fixed number is specified by a variable at function creation time, you can write a function that creates the function.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.