How to call subclass methods in a superclass in Python - python

I want to know how to call subclass methods in the superclass.

I believe this is a pattern used often.
class A(object):
def x(self):
self.y()
def y(self):
print('default behavior')
class B(A):
def y(self):
print('Child B behavior')
class C(A):
def z(self):
pass
>>>B().x()
Child B behavior
>>>C().x()
default behavior
It is sort of like an abstract class, but provides default behavior. Can't remember the name of the pattern off the top of my head though.

The point behind a subclass is that it extends and alters the behaviour of the superclass. The superclass can't know how a subclass will extend it.
Edit: But it is well possible that the superclass knows, that the subclass will extend it. Not sure, if this is good design, though.

Here's what I've just tried:
class A(object):
def x(self):
print self.y()
class B(A):
def y(self):
return 1
>>> B().x()
1
So unless you had some specific problem, just call a method from the subclass in the base class and it should just work.

This is a very broad question. As you don't provide example code, I'll just show the easiest example:
class A(object):
def meth1(self, a):
self.meth2(a, a*a)
class B(A):
def meth2(self, a, b):
return b / a
b = B()
b.meth1(10)

I think this is related to using abstract methods. The parent class defines methods that the subclass should implement and the parent class knows that these methods will be implemented. Similar structures exist for example in Java.
Using these in Python is discussed here well: Abstract methods in Python

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

Abstract method inheritance in Python

Let's assume that we have a Python class that makes use of the abc module to define an abstract attribute:
import abc
class A(object):
__metaclass__ = abc.ABCMeta
#abc.abstractproperty
def test_attribute(self):
raise NotImplementedError
Let's now consider to define B that subclasses from A by adding a new method (test_method()), and C that subclasses from B implementing the abstract method originally declared in A:
class B(A):
def test_method(self):
pass
class C(B):
def test_attribute(self):
# Implement abstract attribute
pass
Assuming that I would like to keep B abstract (non-instantiable), shall I redefine the abstract property (test_attribute) and the metaclass assignment also in B? Or is it enough to inherit them from A (as in the above code)?
I know that Python allows me to not redefine the abstract methods and thus inherit them from the parent class. Is this correct from a theoretical software engineering perspective?
I'm asking so because if I'm not wrong other languages (such as Java) do not allow inheritance of abstract methods without reimplementing them as abstract...
You've pretty much got all the code there, you can always test it and see if it works ... but as a spoiler, Your design is fine so long as C.test_attribute gets decorated with property.
If you try to make an instance of B, then you'll have problems since the whole abstract interface hasn't been created, but it is fine to create it as a base class for C (and presumably other classes later...)
e.g.:
import abc
class A(object):
__metaclass__ = abc.ABCMeta
#abc.abstractproperty
def foo(self):
pass
class B(A):
def bar(self):
return "bar"
class C(B):
#property
def foo(self):
return "foo"
print C().foo # foo
print C().bar() # bar
print B().foo # TypeError

Calling a superclass method from a subclass in python

I was wondering if a subclass could call its parent static method, and tested it : it works like I hoped!
class A(object):
#classmethod
def static(cls):
print('act on '+cls.__name__)
class B(A):
def foo(self):
print('foo()')
>>> B.static()
act on B
I wanted to know if it had pitfalls to be aware of when using that technique ...
Any advice?
What you are calling is the parent's classmethod, not a staticmethod.
Anyway, both of them are OK and common to be called with a subclass.
In case you override A's classmethod in your B, you can still refer to A.static using super(B, cls).static.

Python classes and __init__ method

I am learning python via dive into python. Got few questions and unable to understand, even through the documentation.
1) BaseClass
2) InheritClass
What exactly happens when we assign a InheritClass instance to a variable, when the InheritClass doesn't contain an __init__ method and BaseClass does ?
Is the BaseClass __init__ method called automatically
Also, tell me other things that happen under the hood.
Actually the fileInfo.py example is giving me serious headache, i am just unable to understand as to how the things are working. Following
Yes, BaseClass.__init__ will be called automatically. Same goes for any other methods defined in the parent class but not the child class. Observe:
>>> class Parent(object):
... def __init__(self):
... print 'Parent.__init__'
... def func(self, x):
... print x
...
>>> class Child(Parent):
... pass
...
>>> x = Child()
Parent.__init__
>>> x.func(1)
1
The child inherits its parent's methods. It can override them, but it doesn't have to.
#FogleBird has already answered your question, but I wanted to add something and can't comment on his post:
You may also want to look at the super function. It's a way to call a parent's method from inside a child. It's helpful when you want to extend a method, for example:
class ParentClass(object):
def __init__(self, x):
self.x = x
class ChildClass(ParentClass):
def __init__(self, x, y):
self.y = y
super(ChildClass, self).__init__(x)
This can of course encompass methods that are a lot more complicated, not the __init__ method or even a method by the same name!

Abstract class + mixin + multiple inheritance in python

So, I think the code probably explains what I'm trying to do better than I can in words, so here goes:
import abc
class foo(object):
__metaclass__ = abc.ABCMeta
#abc.abstractmethod
def bar(self):
pass
class bar_for_foo_mixin(object):
def bar(self):
print "This should satisfy the abstract method requirement"
class myfoo(foo, bar_for_foo_mixin):
def __init__(self):
print "myfoo __init__ called"
self.bar()
obj = myfoo()
The result:
TypeError: Can't instantiate abstract class myfoo with abstract methods bar
I'm trying to get the mixin class to satisfy the requirements of the abstract/interface class. What am I missing?
Shouldn't the inheritance be the other way round? In the MRO foo currently comes before bar_for_foo_mixin, and then rightfully complains. With class myfoo(bar_for_foo_mixin, foo) it should work.
And I am not sure if your class design is the right way to do it. Since you use a mixin for implementing bar it might be better not to derive from foo and just register it with the 'foo' class (i.e. foo.register(myfoo)). But this is just my gut feeling.
For completeness, here is the documentation for ABCs.
i think (tested in similar case) that reversing the baseclasses works:
class myfoo(bar_for_foo_mixin, foo):
def __init__(self):
print "myfoo __init__ called"
self.bar()
so in the mro() it would find a concrete version of bar() before it finds the abstract one. No idea if this is actually what happens in the background though.
Cheers, Lars
PS: the code that worked in python 2.7 (python 3 has a different way to set metaclasses) was:
class A(object):
__metaclass__ = abc.ABCMeta
#abc.abstractmethod
def do(self):
pass
class B(object):
def do(self):
print "do"
class C(B, A):
pass
c = C()

Categories

Resources