I have a class scheme with 2-levels of inheritance. My expectation is that each class constructor would run through- and yet the mid-level class constructor never seems to get hit. What's missing here?
class Base(object):
def __init__(self):
print "BASE"
class Next(Base):
def __init__(self):
super(Base, self).__init__()
print "NEXT"
class Final(Next):
def __init__(self):
super(Next, self).__init__()
print "FINAL"
f = Final()
Outputs:
BASE
FINAL
Why does "NEXT" not print??
You should be calling super() with the current class, not the parent.
class Base(object):
def __init__(self):
super(Base, self).__init__()
print "BASE"
class Next(Base):
def __init__(self):
super(Next, self).__init__()
print "NEXT"
class Final(Next):
def __init__(self):
super(Final, self).__init__()
print "FINAL"
f = Final()
At first glance this might seem redundant ("why can't it just get the class from self?") - but keep in mind that the same self is passed to all three of these __init__ methods when f is created, and that self is always of class Final. Thus, you have to pass super() the class that you want it to find the parent of.
class Base(object):
def __init__(self):
print "BASE"
class Next(Base):
def __init__(self):
super(Next, self).__init__()
print "NEXT"
class Final(Next):
def __init__(self):
super(Final, self).__init__()
print "FINAL"
f = Final()
Related
I am trying to call an instance variable from a "parent" class (subclass) to it's "child" class (subsubclass)
class mainclass():
def __init__(self):
self.mainclassvar1 = "mainclass"
class subclass(mainclass):
def __init__(self):
self.subclassvar1 = "subclass"
def changeval(self):
self.subclassvar1 = "subclassedited"
class subsubclass(subclass):
def __init__(self):
self.subsubclassvar1 = subclass.subclassvar1 #<- naturally this fails
def handler():
main=mainclass()
sub = subclass()
sub.changeval()
subsub = subsubclass()
print(subsub.subsubclassvar1)# <- how do I achieve this? I would expect "subclassedited" but it doesn't
if __name__ == "__main__":
handler()
The above does not work obviously but I am trying to show what I am trying to achieve in my head.
if I change the class subsubclass(subclass) as follows it semi-works:
class subsubclass(subclass):
def __init__(self):
subclass.__init__(self)
self.subsubclassvar1 = self.subclassvar1
however the returned value is the original default value of subclass instead of the expected subclassedited.
I am not sure if I should even be trying to do this but I've got some code where the logic has now come to this point and I want to try see if I can get details from the middle class in to the final child class in their final modified states instead of the defaults and without refactoring a lot of code.
Each __init__ method should be invoking the parent's __init__ method, so that the instance is properly initialized for all the classes in the hierarchy.
class mainclass:
def __init__(self):
super().__init__()
self.mainclassvar1 = "mainclass"
class subclass(mainclass):
def __init__(self):
super().__init__()
self.subclassvar1 = "subclass"
def changeval(self):
self.subclassvar1 = "subclassedited"
class subsubclass(subclass):
def __init__(self):
super().__init__()
# Not sure why you would really need this, but...
self.subsubclassvar1 = self.subclassvar1
There's no reason, though that subsub.subclassvar1 should be related to sub.subclassvar1, though. Calling sub.changeval() has nothing to do with subsub.
I would like to implement a widget system similar to FLTK using python in a 3D world.
I simplified my code to the following. I don't get the correct answer. The function is not overwritten even if I change the variable.
def callbacks():
print("callback")
def create():
print ("override")
def default():
print("default")
class f1(object):
def __init__(self):
self.test=default
pass
def docallback(self):
self.test()
class f2(f1):
def __init__(self):
self.test=create
super().__init__()
class f3(f2):
def __init__(self):
self.test=callbacks
super().__init__()
t1=f1()
t2=f2()
t3=f3()
t1.docallback()
t2.docallback()
t3.docallback()
You should be calling super().__init__() first in this case:
class f1(object):
def __init__(self):
self.test = default
def docallback(self):
self.test()
class f2(f1):
def __init__(self):
super().__init__()
self.test = create
class f3(f2):
def __init__(self):
super().__init__()
self.test = callbacks
These 'constructors' call super().__init__() first (which makes assignments to self.test), but then immediately assigns the correct value to self.test itself.
f1.__init__ should use default as the default value of a parameter, not a hard-coded assignment.
class f1:
def __init__(self, test=default):
self.test = test
Then f2 and f3 can simply provide different arguments when using super().
class f2:
def __init__(self):
super().__init__(create)
class f3:
def __init__(self):
super().__init__(callbacks)
class Person:
def _init_(self):
self.A=1
class Employee(Person):
def _init_(self):
print(A)
object1=Person()
object2=Employee()
There are actually multiple problems with that code, besides the misspelled constructor...
Your _init_ method should be __init__, otherwise it's not a constructor but just a method that happens to be called _init_, and thus never called.
You have to call the constructor of the super-class, or A will not be set, e.g. using super().__init__() or Person.__init__(self)
You have to use self.A to read the field A of the instance; otherwise it will look for a local variable called A
This should work:
class Person:
def __init__(self): # misspelled
self.A = 1
class Employee(Person):
def __init__(self): # misspelled
super().__init__() # call super constructor
print(self.A) # use self.A
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?
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'
your init function needs to call the parent init
class Child1(Parent):
def __init__(self):
self.x = 'x'
Parent.__init__(self)
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.
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
I have this code:
class main():
params = {}
class a(main):
def __init__(self):
self.params['test'] = "111aa"
print self.params
class b(main):
def __init__(self):
self.params['be'] = "222bbb"
print self.params
a()
#{'test': '111aa'}
b()
#{'test': '111aa', 'be': '222bbb'}
I need from b to print only {'be': '222bbb'}
Is there any way how to do it ?
Thanks
Try this:
class main(object): # use new-style classes!
def __init__(self):
self.params = {}
class a(main):
def __init__(self):
super(a, self).__init__()
self.params['test'] = "111aa"
print self.params
class b(main):
def __init__(self):
super(b, self).__init__()
self.params['be'] = "222bbb"
print self.params
Notice that in your code params was defined as a class attribute. By defining it in __init__ of the superclass, we're stating that it's an instance attribute. Also notice that the subclasses call __init__ on the superclass.
In this way, we're making sure that each instance has its own params attribute, without sharing it. You can't expect to share an object between instances and have each one with different values for it, it's a contradiction.