Say that, for example, I have two (python (3.3)) classes a and b with their own methods:
class a:
def m1(self):
print("Hi 1")
def m2(self):
print("Hi 2")
##...other methods...
class b(a):
def k1(self):
print("Other hi")
How do I make it so that class b inherits all methods from a except (for example) m2? (besides copy/paste, that doesn't count.) So the expression a.m2() would be legitimate, but b.m2() would throw an AttributeError.
You can get the effect that you want by making 'a' and 'b' siblings rather than parent and child. This might work for you:
class p:
def m1(self):
print("Hi 1")
class a(p):
def m2(self):
print("Hi 2")
class b(a):
def k1(self):
print("Other hi")
So these methods are now all valid, the others will throw AttributeErrors:
a.m1()
a.m2()
b.m1()
b.k1()
Why would you want to do that? The whole point of class inheritance is to be able to test that instances of b are also instances of a; isinstance(b(), a) is True for a reason. By removing methods from b you are breaking that model badly.
Instead make a have fewer methods, and add c to have those that b doesn't need:
class a:
def m1(self):
print("Hi 1")
##...other methods...
class b(a):
def k1(self):
print("Other hi")
class c(a):
def m2(self):
print("Hi 2")
Or, you could not inherit from a and just copy methods from a as needed:
class b:
# copied methods
m1 = a.m1
def k1(self):
print("Other hi")
Now b isa a is no longer true, the expectation that all of a's methods are implemented won't be there anymore.
If a is entirely out of your control and there are too many methods to copy, perhaps use proxying with __getattr__ and passing through anything but m2. A last ditch method could be to implement m2 and raise AttributeError, but that should be a last resort only.
If b inherits from a, it's supposed to inherit every method. That's inheritance about. But if it's necessary to do this (note that is not recommended) you could override the m2() method, so it raises an Exception when called.
class b(a):
def m2(self):
raise Exception("...")
That does not really make sense. The point of inheritance is so that the inheriting object is exactly compatible to the base type. This is the Liskov substitution principle: Wherever an object of the original type is acceptable, an object of the derived type also will be.
If you change your derived type to not have some members of the base type, then you are violating this principle. With the dynamic typing in Python, it wouldn’t be that much of a problem but it’s still violating the idea behind it.
So you really just shouldn’t do that.
Related
In a python program, I implemented some class A, and a subclass B which extends some of A's methods and implements new ones. So it's something that looks like this.
class A:
def method(self):
print("This is A's method.")
class B(A):
def method(self):
super().method()
print("This is B's method.")
def another_method(self):
pass
Later, I wanted to use an object which would have access to all of B's methods, except for a small change in method: this object would have to first call A.method, and then do other things, different from what I added in B.method. I thought it was natural to introduce a class C which would inherit from B but modify method, so I defined C like this.
class C(B):
def method(self):
super(B, self).method()
print("This is C's method.")
Everything seems to work as I expect. However, I stumbled across this question and this one, which both address similar problems as what I described here. In both posts, someone quickly added a comment to say that calling a grandparent method in a child when the parent has overridden this method is a sign that there is something wrong with the inheritance design.
How should I have coded this? What would be a better design? Of course this is a toy example and I guess the answer might depend on the actual classes I defined. To give a more complete picture, let's say the method method from the example represents a single method in my actual program, but the method another_method represents many different methods.
Python 2.7.6 on Linux.
I'm using a test class that inherits from a parent. The parent class holds a number of fields that are common to many child classes, and I need to call the parent setUp method to initialize the fields. Is calling ParentClass.setUp(self) the correct way to do this? Here's a simple example:
class RESTTest(unittest.TestCase):
def setUp(self):
self.host = host
self.port = port
self.protocol = protocol
self.context = context
class HistoryTest(RESTTest):
def setUp(self):
RESTTest.setUp(self)
self.endpoint = history_endpoint
self.url = "%s://%s:%s/%s/%s" %(self.protocol, self.host, self.port, self.context, self.endpoint)
def testMe(self):
self.assertTrue(True)
if __name__ == '__main__':
unittest.main()
Is this correct? It seems to work.
You would use super for that.
super(ChildClass, self).method(args)
class HistoryTest(RESTTest):
def setUp(self):
super(HistoryTest, self).method(args)
...
In Python 3 you may write:
class HistoryTest(RESTTest):
def setUp(self):
super().method(args)
...
which is simpler.
See this answer:
super() lets you avoid referring to the base class explicitly, which can be nice. But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven't already.
Multiple inheritance
To (try to) answer the question in your comment:
How do you specify which super method you want to call?
From what I understand of the philosophy of multiple inheritance (in Python), you don't. I mean, super, along with the Method Resolution Order (MRO) should do things right and select the appropriate methods. (Yes methods is a plural, see below.)
There are a lot of blog posts / SO answers about this you can find with keywords "multiple inheritance", "diamond", "MRO", "super", etc. This article provides a Python 3 example I found surprising and didn't find in other sources:
class A:
def m(self):
print("m of A called")
class B(A):
def m(self):
print("m of B called")
super().m()
class C(A):
def m(self):
print("m of C called")
super().m()
class D(B,C):
def m(self):
print("m of D called")
super().m()
D().m()
m of D called
m of B called
m of C called
m of A called
See? Both B.m() and C.m() are called thanks to super, which seems like the right thing to do considering D inherits from both B and C.
I suggest you play with this example like I just did. Adding a few prints, you'll see that, when calling D().m(), the super().m() statement in class B itself calls C.m(). Whereas, of course, if you call B().m() (B instance, not D instance), only A.m() is called. In other words, super().m() in B is aware of the class of the instance it is dealing with and behaves accordingly.
Using super everywhere sounds like the silver bullet, but you need to make sure all classes in the inheritance schema are cooperative (another keyword to dig for) and don't break the chain, for instance when expecting additional parameters in child classes.
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
Suppose that I have the following python base class:
class BaseClass(object):
def a():
"""This method uses method b(), defined in the inheriting class"""
And also a class that inherites BaseClass:
class UsedByUser(BaseClass):
def b():
"""b() is defined here, yet is used by the base class"""
My user would only create instances of class UsedByUser. Typical use would be:
if __name__ == '__main__':
# initialize the class used by the user
usedByUser = UsedByUser()
# invoke method a()
usedByUser.a()
My questions is, is the above use problematic? is this a valid approach, or must I also define method b() in BaseClass and then override it in UsedByUser?
I would define the b method in the BaseClass too:
class BaseClass(object):
def b(self):
raise NotImplementedError('b must be implemented by a subclass')
Remember: explicit is better than implicit and given that the method a needs the method b anyways, better raise a meaningful exception rather than a general AttributeError.
It is worth to point out that this is absolutely NOT needed from a syntactic point of view, but it adds clarity to the code and enforces the subclass to provide an implementation.
The use is correct. Classes can define methods that can be overriden
from subclasses, but those can also define new methods. Defining
every method needed for subclasses in the superclass seems a bit
senseless. (Since object then would also need to have every
function defined ?)
A subclass often has a different bahviour to another subclass.
class Vehicle(object):
def Refuel(self):
# ...
class Plane(Vehicle):
def Fly(self):
# ...
class Car(Vehicle):
def Drive(self):
# ...
Edit: I misread the code.
If only you create a subclass of it and make sure subclasses have B(), then it's theoratically ok, but bad style. It makes more sense and is safer to give the superclass attributes and methods that are used by the superclass. -> Define B()
Sounds like you want A to call a protected member function of UsedByUser that can't go in the abstract BaseClass). Try prefixing the protected function with an underscore (although note this is just a convention used by Python and not strictly checked, as mentioned here).
class BaseClass(object):
def A(self):
print "Grettings from A"
self._B()
def _B(self):
raise NotImplementedError('b must be implemented by a subclass')
class UsedByUser(BaseClass):
def _B(self):
""" prefix with underscore is a python convention for a protected member function """
print "B rocks!"
if ( __name__=='__main__' ):
usedByUser = UsedByUser()
usedByUser.A()
Find more on this convention in the PEP guidelines.
Edit:
As GaretJax suggested, I added a BaseClass _B method for clarity. Nice tip!
BaseClass can't assume that a UsedByUser object exists, so it can't use a B() method from it. You probably want to define a B() in BaseClass, that either does nothing (if it's sensible to attempt B() with something that doesn't support it) or raises an exception (if it's not sensible to attempt B()).
If you tell us what A and B are in your use case, we may be able to advise you better.
I need to write a base class (in this example, class A) that will likely, but not always, be subclassed. I want to call the 'Run' method from the base class only if its not subclassed, else only call the the 'Run' method from the subclasses.
This is what I have, it seems to work but I'm wondering if there is an easier or more Pythonic way.
class A(object):
def __init__(self):
pass
def Run(self):
print "Calling A.Run()"
class B(A):
def __init__(self):
A.__init__(self)
pass
def Run(self):
print "Calling B.Run()"
subs = A.__subclasses__()
if subs: inst = [i() for i in subs]
else: inst = [A()]
[each.Run() for each in inst]
What you have looks correct, except that most programmers would look at the B.Run method and think: "Oh, he forgot to call super. Let me just add that..." but I'm sure you'd explain what you're doing in your real implementation :)
If you're worried about something like slicing in C++, then be reassured. What you have is good.
As for making it "easier", I'm not sure how you could simplify it aside from removing A's empty __init__ function and removing pass from B's __init__.
I want to call the 'Run' method from the base class only if its not subclassed, else only call the the 'Run' method from the subclasses.
This is what happens by default, the most specific method is called.
If you really don't want the base method to be available from subclasses, you can write something like this:
class C(object):
def Run(self):
if self.__class__ != C:
raise NotImplementedError("You need to override this method")