I have a class Father whom I call run method to do the work. I inherit this class with a Child class. This look like this:
class Father:
def __init__(self):
...
def run(self):
work1()
work2()
....
class Child(Father):
def run(self):
pass
Usually, I use pass, as most of the time, children do same things as father, just being called from distinct contexts. However, sometimes the behavior changes. But when it does, work1, work2, and so on from Father are still being executed. Only a last workn should be added.
How is it possible to override run method without having to copy the whole code from Father.run, and just adding a last work instruction? I have tried this, which is working:
class Father:
def run(self):
work1()
...
run_additionnal_stuf()
def run_additionnal_stuf(self):
pass
class Child(Father):
def run_additionnal_stuf(self):
work()
However, is there any solution more elegant?
First of all, if your Child class doesn't change a method you don't need to define it with pass. Simply do nothing and thanks to inheritance magic, the child instance will also have that method.
As to your actual question, if you only want to add functionality to a child instance, you can use super. Indeed, from the docs:
This is useful for accessing inherited methods that have been
overridden in a class.
So you could do:
class Child(Father):
def run(self):
super().run()
work_n()
A simple demonstration:
class Father:
def run(self):
print("In Father")
class Child(Father):
def run(self):
super().run()
print("In Child")
f = Father()
c = Child()
f.run()
c.run()
And this expectedly prints out:
In Father
In Father
In Child
Related
I have a pretty big class that i want to break down in smaller classes that each handle a single part of the whole. So each child takes care of only one aspect of the whole.
Each of these child classes still need to communicate with one another.
For example Data Access creates a dictionary that Plotting Controller needs to have access to.
And then plotting Controller needs to update stuff on Main GUI Controller. But these children have various more inter-communication functions.
How do I achieve this?
I've read Metaclasses, Cooperative Multiple Inheritence and Wonders of Cooperative Multiple Inheritence, but i cannot figure out how to do this.
The closest I've come is the following code:
class A:
def __init__(self):
self.myself = 'ClassA'
def method_ONE_from_class_A(self, caller):
print(f"I am method ONE from {self.myself} called by {caller}")
self.method_ONE_from_class_B(self.myself)
def method_TWO_from_class_A(self, caller):
print(f"I am method TWO from {self.myself} called by {caller}")
self.method_TWO_from_class_B(self.myself)
class B:
def __init__(self):
self.me = 'ClassB'
def method_ONE_from_class_B(self, caller):
print(f"I am method ONE from {self.me} called by {caller}")
self.method_TWO_from_class_A(self.me)
def method_TWO_from_class_B(self, caller):
print(f"I am method TWO from {self.me} called by {caller}")
class C(A, B):
def __init__(self):
A.__init__(self)
B.__init__(self)
def children_start_talking(self):
self.method_ONE_from_class_A('Big Poppa')
poppa = C()
poppa.children_start_talking()
which results correctly in:
I am method ONE from ClassA called by Big Poppa
I am method ONE from ClassB called by ClassA
I am method TWO from ClassA called by ClassB
I am method TWO from ClassB called by ClassA
But... even though Class B and Class A correctly call the other children's functions, they don't actually find their declaration. Nor do i "see" them when i'm typing the code, which is both frustrating and worrisome that i might be doing something wrong.
Is there a good way to achieve this? Or is it an actually bad idea?
EDIT: Python 3.7 if it makes any difference.
Inheritance
When breaking a class hierarchy like this, the individual "partial" classes, we call "mixins", will "see" only what is declared directly on them, and on their base-classes. In your example, when writing class A, it does not know anything about class B - you as the author, can know that methods from class B will be present, because methods from class A will only be called from class C, that inherits both.
Your programming tools, the IDE including, can't know that. (That you should know better than your programming aid, is a side track). It would work, if run, but this is a poor design.
If all methods are to be present directly on a single instance of your final class, all of them have to be "present" in a super-class for them all - you can even write independent subclasses in different files, and then a single subclass that will inherit all of them:
from abc import abstractmethod, ABC
class Base(ABC):
#abstractmethod
def method_A_1(self):
pass
#abstractmethod
def method_A_2(self):
pass
#abstractmethod
def method_B_1(self):
pass
class A(Base):
def __init__(self, *args, **kwargs):
# pop consumed named parameters from "kwargs"
...
super().__init__(*args, **kwargs)
# This call ensures all __init__ in bases are called
# because Python linearize the base classes on multiple inheritance
def method_A_1(self):
...
def method_A_2(self):
...
class B(Base):
def __init__(self, *args, **kwargs):
# pop consumed named parameters from "kwargs"
...
super().__init__(*args, **kwargs)
# This call ensures all __init__ in bases are called
# because Python linearize the base classes on multiple inheritance
def method_B_1(self):
...
...
class C(A, B):
pass
(The "ABC" and "abstractmethod" are a bit of sugar - they will work, but this design would work without any of that - thought their presence help whoever is looking at your code to figure out what is going on, and will raise an earlier runtime error if you per mistake create an instance of one of the incomplete base classes)
Composite
This works, but if your methods are actually for wildly different domains, instead
of multiple inheritance, you should try using the "composite design pattern".
No need for multiple inheritance if it does not arise naturally.
In this case, you instantiate objects of the classes that drive the different domains on the __init__ of the shell class, and pass its own instance to those child, which will keep a reference to it (in a self.parent attribute, for example). Chances are your IDE still won't know what you are talking about, but you will have a saner design.
class Parent:
def __init__(self):
self.a_domain = A(self)
self.b_domain = B(self)
class A:
def __init__(self, parent):
self.parent = parent
# no need to call any "super...init", this is called
# as part of the initialization of the parent class
def method_A_1(self):
...
def method_A_2(self):
...
class B:
def __init__(self, parent):
self.parent = parent
def method_B_1(self):
# need result from 'A' domain:
a_value = self.parent.a_domain.method_A_1()
...
This example uses the basic of the language features, but if you decide
to go for it in a complex application, you can sophisticate it - there are
interface patterns, that could allow you to swap the classes used
for different domains, in specialized subclasses, and so on. But typically
the pattern above is what you would need.
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.
class Parent():
def __init__(self):
self.child = Child()
class Child():
def __init__(self):
# get Parent instance
self.parent = self.Instantiator()
I know this isn't proper encapsulation but for interest's sake...
Given a "Parent" class that instantiates a "Child" object, is it possible from within Child to return the Parent object that instantiated it? And if no, I'm curious, do any languages support this?
To answer the question, no, there's no way1 the child instance knows about any classes which contain references to it. The common2 way to handle this is:
class Parent(object):
def __init__(self):
self.child = Child()
self.child._parent = self
1 Of course, this isn't strictly true. As another commentor noted, you can extract the stack frame from the executing code within the __init__ method, and examine the f_locals dictionary for the self variable for the frame before the currently executing one. But this is complicated, and prone to error. Highly unrecommended.
2 A slightly better way to handle this (depending on the specific needs of the program) might be to require the parent to pass itself to the child, like so:
class Parent(object):
def __init__(self):
self.child = Child(self)
class Child(object):
def __init__(self, parent):
self._parent = parent
Here's a reasonably-simple metaclass solution to the problem:
import functools
class MetaTrackinits(type):
being_inited = []
def __new__(cls, n, b, d):
clob = type.__new__(cls, n, b, d)
theinit = getattr(clob, '__init__')
#functools.wraps(theinit)
def __init__(self, *a, **k):
MetaTrackinits.being_inited.append(self)
try: theinit(self, *a, **k)
finally: MetaTrackinits.being_inited.pop()
setattr(clob, '__init__', __init__)
def Instantiator(self, where=-2):
return MetaTrackinits.being_inited[where]
setattr(clob, 'Instantiator', Instantiator)
return clob
__metaclass__ = MetaTrackinits
class Parent():
def __init__(self):
self.child = Child()
class Child():
def __init__(self):
self.parent = self.Instantiator()
p = Parent()
print p
print p.child.parent
a typical output, depending on the platform, will be something like
<__main__.Parent object at 0xd0750>
<__main__.Parent object at 0xd0750>
You could obtain a similar effect (in 2.6 and later) with a class decorator, but then all classes needing the functionality (both parent and children ones) would have to be explicitly decorated -- here, they just need to have the same metaclass, which may be less intrusive thanks to the "module-global __metaclass__ setting" idiom (and the fact that metaclasses, differently from class-decorations, also get inherited).
In fact, this is simple enough that I would consider allowing it in production code, if the need for that magical "instantiator" method had a proven business basis (I would never allow, in production code, a hack based on walking the stack frames!-). (BTW, the "allowing" part comes from the best-practice of mandatory code reviews: code changes don't get into the trunk of the codebase without consensus from reviewers -- this how typical open source projects work, and also how we always operate at my employer).
Here's an example based off of some of Chris B.'s suggestions to show how absolutely terrible it would be to inspect the stack:
import sys
class Child(object):
def __init__(self):
# To get the parent:
# 1. Get our current stack frame
# 2. Go back one level to our caller (the Parent() constructor).
# 3. Grab it's locals dictionary
# 4. Fetch the self instance.
# 5. Assign it to our parent property.
self.parent = sys._getframe().f_back.f_locals['self']
class Parent(object):
def __init__(self):
self.child = Child()
if __name__ == '__main__':
p = Parent()
assert(id(p) == id(p.child.parent))
Sure that'll work, but just never try to refactor it into a seperate method, or create a base class from it.
you could* try to use the traceback module, just to prove a point.
**Don't try this at home, kids*
This can be done in python with metaclasses.