I'm trying to override two parent class functions train and eval in a ChildClass. In the parent class, eval() basically calls train(). However, I realize that when I write my code as below, eval() in the parent class is trying to call the function train() in ChildClass - I would like eval() in the parent class to call train() in the parent class instead.
I'm just wondering if there is any clean solutions to make changes to ChildClass that would allow the parent class to call the parent train() function?
class ChildClass(nn.Module):
def __init__(self):
super(ChildClass, self).__init__()
def train(self):
super(ChildClass, self).train()
def eval(self):
super(ChildClass, self).eval()
Parent class is in a Python Package (pytorch), so no changes should be made:
class Module(object):
#...
def train(self, mode=True):
# ...
return self
def eval(self):
return self.train(False)
Your overridden methods are not doing anything except invoking the parent (at least from the code you have shared).
So, I think you want to have a method that has the same steps as in train()/eval().
I guess you don't need to override train() or eval(), instead add method(s) in your child class and call parent train()/eval() in whichever order you want to mix them.
Related
It is first time I try to use super(), I tried many little changes to this code, but with all I got error on line where super() is.
I saw similar questions on SO, but they are not working in my case or I do something wrong
Could you help me to call getMessagesBodies() from list() ?
class Gmail:
def getMessagesBodies(self, text):
return self.unpackPayload(text)
def unpackPayload(self, text):
return (text)
class getMessages:
def __init__(self):
self.service = auth()
def list(self,text):
return super(self).getMessagesBodies(text) # error here, how to call getMessagesBodies properly?
The problem is that you never specified what the parent class was for the getMessages class.
You should define the class like so:
class getMessages(Gmail):
Unless your child class is overriding the getMessagesBodies() function, you actually do not have to use super() to specify that you want to call the parent function. By using self.getMessagesBodies() in your child class it will automatically call the parent's function since the child inherits all the same functions from the parent.
So you can call the function without using super like:
self.getMessagesBodies(text)
Also, just a tip is that getMessages seems more like a function name then a class. Usually classes are fully capitalized and are an object, not an action.
Please take a look at the sample code below. The parent class, needs to call the setup() function, but that function needs to be defined/overwritten in the child class. But the sample code below shows that when child is initialized and called super(), the super's method calls the parent setup() which contains nothing.
Intended behavior is when child is instantiated, it calls parent's __init__ by using super() and automatically call the setup function defined in the child. Setting Human.setup() as abstract class also did not seem to work.
Google can only find information on how to call parent's method from child, but this case is the reverse, "How to call child's method from parent". Or is it not possible in python3?
The reason it needs to call the setup function of the child is due to each child class will be having a different setup procedure. But they share most of the methods defined in the parent class.
class Human(object):
def __init__(self):
self.setup()
def setup(self):
pass
class child(Human):
def __init__(self):
super()
def setup(self):
self.name = "test"
>>> A = child()
>>> A.name
AttributeError: 'child' object has no attribute 'name'
You are not calling Human's __init__ from child's __init__.
super() gives you a handle through which to call superclass methods, but you need to do that via method calls on super().
In this case:
class Child(Human):
def __init__(self):
super().__init__()
Suppose I have two classes in Python as below:
class Parent(object):
def __init__(self):
self.num = 0
def fun1(self):
print 'p.fun1'
def fun2(self):
self.fun1()
print 'p.fun2'
and
from parent import Parent
class Child(Parent):
def __init__(self):
super(Child,self).__init__()
def fun1(self):
print 'c.fun1'
def fun2(self):
super(Child, self).fun2()
print 'c.fun2'
and if I call fun2 of Child
from child import Child
test = Child()
test.fun2()
I get output:
c.fun1
p.fun2
c.fun2
Which means the call of Child.fun2() leads to Parent.fun2(). But inside the Parent.fun2(), I use self.fun1() which in this case interpreted as Child.fun1() in my test.
But I really want the class Parent to be individual and the call of Parent.fun2() always uses Parent.fun1() inside it.
How can I avoid this?
I only know that I can make Parent.fun1() private into Parent.__fun1(). But I also have some instances of Parent where I need to use Parent.fun1() outside this class. That means I really need to override the fun1().
That's how inheritance is supposed to work. For the behavior you need, you might want to reconsider Parent & Child class's relationship, or change the method names or at least make the Parent methods classmethods or staticmethods.
This should work for your need, but I don't really like it.
class Parent(object):
def __init__(self):
self.num=0
def fun1(self):
print 'p.fun1'
def fun2(self):
Parent.fun1(self)
print 'p.fun2'
Child class can remain the same.
In all classes accessed in the inheritance chain, self will always point to the instance of class actually instantiated and not the current class accessed in super call (or in order to find method/attribute for that matter). So self.fun2 will always point to the method of Child class.
There is a mechanism called Name Mangling:
Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.
Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls
Python Classes Documentation
This should work:
class Parent(object):
def __init__(self):
self.num = 0
def fun1(self):
print 'p.fun1'
def fun2(self):
self.__fun1()
print 'p.fun2'
__fun1 = fun1
I am developing a system, which has a series of single multilevel inheritance hierarachy. one of the methods (applicable to all the classes) has to perform the same thing for most of the classes, which is to pass a list to its parent class.
I know that if one doesn't define a method in one of the inherited classes, its parents' methods are used. But when we use the super method, we need to mention the name of the class being called.
One method I know to achieve this is to redefine the method at every class with class name as argument. Is there any elegant method where I can define it once at the topmost parent, and then override it only when necessary?
The implementation right now looks like this
class a(object):
def __init__(self):
self.myL = list()
print 'hello'
class b(a):
def __init__(self):
super(b,self).__init__()
def resolve(self, passVal):
print passVal
self.myL.append(passVal)
super(b,self).resolve(passVal+1)
class c(b):
def __init__(self):
super(c,self).__init__()
def resolve(self, passVal):
print passVal
self.myL.append(passVal)
super(c,self).resolve(passVal+1)
Instead if I can define resolve in class a, and then all other classes inherit the method from it. I understand a will never be able to use it. but redefining the method seems a lot unnecessary extra work.
I have a function which return instances of the class Parent:
def generateParent():
do_stuff
return Parent(some_parameters)
Now I want to init a subclass of Parent with the results of a call to generateParent():
class Child(Parent):
def __new__():
return generateParent(some_other_parameters)
The problem is, when I override some methods from Parent in Child and then call them in instances of Child in my program, the original Parent method gets called instead of the new one from Child. Am I doing something wrong here? Am I using the correct design here for my task?
EDIT: I don't have access neither to Parent nor generateParent()
Solution(thanks to #Paul McGuire's answer):
class Child(object):
def __init__(self):
self.obj = generateParent()
def __getattr__(self, attr):
return getattr(self.obj, attr)
Since generateParent is not your code, then instead of inheritance, you might want to use containment and delegation. That is, instead of defining a subclass, define a wrapper class that contains the generated object, forwards method calls to it when needed, but can add new behavior or modified behavior in the wrapper.
In this question, the OP had a similar situation, having a class generated in a libary, but wanting to extend the class and/or modify some behavior of the class. Look at how I added a wrapper class in that question, and you might consider doing something similar here.
Here's one way to do it:
def generateChild(params):
p = generateParent(params)
p.__class__ = Child
return p
class Child(Parent):
# put method overrides etc here
childinstance = generateChild(some_params)
Perhaps you want generateParent to be able to make instances of other classes:
def generateParent(cls=Parent):
do_stuff
return cls(some_parameters)
Now this will make a Child object:
child = generateParent(Child)
Or perhaps you want Parent and all of its derived classes to use common initialization code?
class Parent(object):
def __init__(self):
do_stuff
# init from some_parameters
class Child(Parent):
# blah..
Make your Child object able to copy information from a created Parent object:
class Child(Parent):
def __init__(self):
model_parent = generateParent()
self.a = model_parent.a
self.b = model_parent.b
# etc.