difference between multiple inheritance and multilevel inheritance - python

one non mature question on inheritance :-)
Say I have classes
class A (B)
{code}
class B(C)
{code}
class C(object)
def function1()
{code}
I can access function1() with following code
obj=A()
obj.function1()
Since we have multilevel inheritance, we can get it.
I believe I can do the same using multiple inheritance ? like
class A(B,C) ?
What is the difference here?
Where can i get true use case of multilevel inheritance over multiple inheritance?

class Base1:
pass
class Base2:
pass
class MultiDerived(Base1, Base2):
pass
this is an example of multiple inheritance . In that a single class can inherit multiple classes .
In multilevel if you have a class
class A
{code}
class B (A)
{code}
class C (B)
{code}
in this you Inherit class A property in class C when you Inherited class b . so if a class has inherited some class and you dont want to inherit property of superclass than multiple inheritance is used .
for more info with diagram refer to this link :- https://www.programiz.com/python-programming/multiple-inheritance

In your particular example both definitions of class A will have the same effect. But if you add function1 to class B as well, then you can decide which version of function1 will be called from class A, by adjusting multiple inheritance order when defining class A.
So you can do this like this:
class A(B,C)
or like that:
class A(C,B)

Problem with multiple inheritance is function overloading. Imagine this:
class A:
def test(self):
print("class A")
class B:
def test(self):
print("class B")
class C(A, B):
pass
c = C()
c.test()
Can you guess what the output will be? (it's class A). In case of multilevel inheritance you have more control over overriding methods. It's less likely for you to make mistake using multilevel inheritance. You can simple overlook that your parent classes are implementing same method for your child class.
But to be honest, as long as you know how to handle multiple inheritance in python and you know the problems with it - you should be fine using either. Check official python documentantion for the multiple inheritance.

Related

Multilevel abstraction with interface and inheritance in Python

I'm not exactly sure how to phrase this question, hence the strange title. I also have not been able to find any information on this after searching, so hopefully this isn't a duplicate and I'm just searching for the wrong words. Anyhow, here is the situation, I have an abstract base class with some methods in it, which is inherited by a class. I don't want to set one of the methods in this base class, as this class is meant to be inherited by other classes to provide the common functionality they all share. Something like:
class A(metaclass=abc.ABCMeta):
#abc.abstractmethod
def fun1(self):
pass
#abc.abstractmethod
def fun2(self):
pass
class B(A):
def fun1(self):
#do work here
#abc.abstractmethod
def fun2(self): # Intent to have the final classes define this
pass
class C(B):
def fun2(self):
# do work here
class D(B):
def fun2(self):
# do work here
I would like to keep the function as an ABC.meta to force implementation on the final children, but because there can be multiple types of class B in this case all inheriting from the interface, I want to keep the initial virtulization of the method at this root class, but have a way for class B to enforce that it's sub-classes must implement this. The code works just find if I don't add the abstract method to class B, but that is awkward since subclassess must implement the method and shouldn't have to look all the way up to the interface to figure out everything they need to implement. As written, it will error out because class B cannot declare the method as an abc.abstract. If I don't declare it as an abstract there is no way to enforce the child class has to implement the method.
I hope my convoluted way of writing this makes sense to someone out there...
Thanks!
You probably should not redefine fun2 as an abstract method in the concrete class B. You are creating a set of rules for your interface, but immediately violating them when you do that.
Instead, either define a mix-in class or an additional ABC that C and D can inherit.
class A(metaclass=abc.ABCMeta):
#abc.abstractmethod
def fun1(self):
pass
class A2(metaclass=abc.ABCMeta):
#abc.abstractmethod
def fun2(self):
pass
class B(A):
def fun1(self):
print('hello')
class B2(A2):
def fun2(self):
print('world')
class C(B, B2):
pass
class D(B, B2):
pass

How to refer from child class to child class of another class

I know the title of the question is very confusing. I couldn't come up with anything meaningful. Let me explain it.
I have two classes, let's call them A and B:
class A(object):
def get_instance_of_b():
return B()
class B(object):
pass
In it I have a method that refers to instance of class B.
I have 4 classes that inherit from A and another 4 classes that inherit from class B. Now what I want is to avoid rewriting get_instance_of_b() method. Class A1 (child of A) should get an instance of B1 (child of B) and so on.
What is the best way to do it? Or maybe I'm going wrong with classes structure?
To give a context to what my classes do: class A processes data and class B validates input parameters. All children of class A share some general parameters but children classes also have their own specific parameters.
You should have an explicit mapping of your A classes (your "processors") to your B classes (your "validators"), and do the lookup that way.
class A(object):
def get_validator(self):
return validators[self.__class__]()
class A1(A):
...
class B(object):
...
class B1(B):
...
validators = {A:B, A1:B1}
And use as such:
>>> a1 = A1()
>>> a1.get_validator()
<__main__.B1 object at ...>

Python multiple inheritance, calling second base class method, if both base classes holding same method

class A:
def amethod(self): print("Base1")
class B():
def amethod(self): print("Base3")
class Derived(A,B):
pass
instance = Derived()
instance.amethod()
#Now i want to call B method amethod().. please let me know the way.**
Python multiple inheritance, calling second base class method, if both base classes holding same method
try to use composition
+Avoid multiple inheritance at all costs, as it's too complex to be reliable. If you're stuck with it, then be prepared to know the class hierarchy and spend time finding where everything is coming from.
+Use composition to package code into modules that are used in many different unrelated places and situations.
+Use inheritance only when there are clearly related reusable pieces of code that fit under a single common concept or if you have to because of something you're using.
class A:
def amethod(self): print("Base1")
class B:
def amethod(self): print("Base3")
class Derived2:
def __init__(self):
self.a = A()
self.b = B()
def amthodBase1(self):
self.a.amethod()
def amthodBase3(self):
self.b.amethod()
instance2 = Derived2()
instance2.amthodBase1()
instance2.amthodBase3()
galaxyan's answer suggesting composition is probably the best one. Multiple inheritance is often complicated to design and debug, and unless you know what you're doing, it can be difficult to get right. But if you really do want it, here's an answer explaining how you can make it work:
For multiple inheritance to work properly, the base classes will often need to cooperate with their children. Python's super function makes this not too difficult to set up. You often will need a common base for the classes involved in the inheritance (to stop the inheritance chain):
class CommonBase:
def amethod(self):
print("CommonBase")
# don't call `super` here, we're the end of the inheritance chain
class Base1(CommonBase):
def amethod(self):
print("Base1")
super().amethod()
class Base2(CommonBase):
def amethod(self):
print("Base2")
super().amethod()
class Derived(Base1, Base2):
def amethod(self):
print("Derived")
super().amethod()
Now calling Derived().amethod() will print Derived, Base1, Base2, and finally CommonBase. The trick is that super passes each call on to the the next class in the MRO of self, even if that's not the in the current class's inheritance hierarchy. So Base1.amethod ends up calling Base2.amethod via super since they're being run on an instance of Derived.
If you don't need any behavior in the common base class, its method body just be pass. And of course, the Derived class can just inherit the method without writing its own version and calling super to get the rest.

Inheritance of class in Python?

Suppose I have a parent class A and a daughter class B. Now A has 10 methods in it and B requires only three of those methods. How can this be done?
There is nothing special to do.
Just inherit class A:
class B(A):
super(B, self).__init__():
Use/override the methods you need and ignore the rest.

Why inheritance in python require the parent class to inherit object explicitly?

Below is two versions of my code:
Non-working one
class A:
def __init__(self):
print "I am A "
class B:
def __init__(self):
print "I am B "
class C(A, B):
def __init__(self):
super(C, self).__init__()
c = C()
This raises exception:
super(C, self).__init__()
TypeError: must be type, not classobj
Working version
class A(object):
def __init__(self):
print "I am A "
class B:
def __init__(self):
print "I am B "
class C(A, B):
def __init__(self):
super(C, self).__init__()
c = C()
If one of the parent class has inherited object explicitly , there is no exception and things works as desired. Any explanation, why?
With the above working one , it prints "I am A" but not "I am B" which means it initializes only Class A and not Class B. HOw to initialize multiple parent classes in children class?
That's because super only works with new-style classes (that inherit from object). In Python 2, classes where object is nowhere in the inheritance hierarchy (like your first example) are called old-style classes, and should never be used anywhere.
It's an old historical artifact from when Python first got OO added to it, and the developers got it wrong. Among other things, new-style classes allow for the use of super, the descriptor protocol (properties), and makes several fixes to the way multiple inheritance is handled. super is one of them, but the most important is the way method resolution order is computed for diamond inheritance cases (A inherits from B and C which both inherit from D). Read more about it here: http://python-history.blogspot.fr/2010/06/method-resolution-order.html
Note that Python 3 ditched old-style classes entirely, and thus in Python 3 all classes are new-style classes and inherit from object, regardless of whether or not they do it explicitly.
super() only works for new-style classes(Any class which inherits from object).So You couldn't pass class object to super.
There are two typical use cases for super. In a class hierarchy with single inheritance, super can be used to refer to parent classes without naming them explicitly, thus making the code more maintainable. This use closely parallels the use of super in other programming languages.
The second use case is to support cooperative multiple inheritance in a dynamic execution environment. This use case is unique to Python and is not found in statically compiled languages or languages that only support single inheritance. This makes it possible to implement “diamond diagrams” where multiple base classes implement the same method. Good design dictates that this method have the same calling signature in every case (because the order of calls is determined at runtime, because that order adapts to changes in the class hierarchy, and because that order can include sibling classes that are unknown prior to runtime).
a typical superclass call looks like this:
class C(B):
def method(self, arg):
super(C, self).method(arg)

Categories

Resources