I'm trying something very basic with Python inheritance:
class Parent:
def __init__(self):
self.text = 'parent'
def getText(self):
print self.text
class Child1(Parent):
def __init__(self):
self.x = 'x'
class Child2(Parent):
def __init__(self):
self.x = 'x'
if __name__ == "__main__":
parent = Parent()
child1 = Child1()
child2 = Child2()
parent.getText()
child1.getText()
child2.getText()
but I keep getting
Child1 instance has no attribute 'text'
how are variables passed to children?
4 Answers 4
You need to call the constructor of the parent classes manually - Here, self.text is initialize in Parent constructor which is never called:
class Child1(Parent):
def __init__ (self):
super(Child1, self).__init__ ()
# or Parent.__init__ (self)
self.x = 'x'
4 Comments
super vs Parent init?super most of the time.self.text from parent in a child? just self.text = 'new text'? or is there another way more suited for inheritance? (I will accept the answer once the timer is down, have 2 minutes left)self object, it's no different than altering it in another method of the object. Just assign a new value to it.Since python 3.6, we can now use the __init_subclass__ function, which is called automatically before __init__ of the Child.
class Parent:
def __init__(self):
self.text = 'parent'
def __init_subclass__(self):
Parent.__init__(self)
def getText(self):
print(self.text)
class Child1(Parent): pass
class Child2(Parent): pass
classes = [Parent(), Child1(), Child2()]
for item in classes:
item.getText()
output
parent
parent
parent
If you use your Parent class more as a "interface", here is another example.
class Animal():
def __init_subclass__(self, sound):
self.sound = sound
def make_sound(self):
print(self.sound)
class Cat(Animal, sound='meow'): pass
class Dog(Animal, sound='woof'): pass
animals = [Cat(), Dog()]
for animal in animals:
animal.make_sound()
output
meow
woof
Comments
your init function needs to call the parent init
class Child1(Parent):
def __init__(self):
self.x = 'x'
Parent.__init__(self)
Comments
In python when you override a function which was supposed to be inherited you override all of it, __init__ is no exception. You should call the functions super method to use the base initializer, or implement the attribute in the constructor you have rewrote.
class Parent:
def __init__(self):
self.text = 'parent'
def getText(self):
print self.text
class Child1(Parent):
def __init__(self):
super(Child1, self).__init__()
self.x = 'x'
child1.getText()
Should work now.
self.textis initialize inParentconstructor which is never called.super().__init__()?pass, that's what it's for (a dummy body).pass, e.g.if a: pass(only for demonstration purpose).pass, if the block is also a function, then adding a docstring also works to prevent python from complaining about the indentation being wrong.