I have a class that is a super-class to many other classes. I would like to know (in the init() of my super-class if the subclass has overridden a specific method.
I tried to accomplish this with a class method, but the results were wrong:
class Super:
def __init__(self):
if self.method == Super.method:
print 'same'
else:
print 'different'
@classmethod
def method(cls):
pass
class Sub1(Super):
def method(self):
print 'hi'
class Sub2(Super):
pass
Super() # should be same
Sub1() # should be different
Sub2() # should be same
>>> same
>>> different
>>> different
Is there any way for a super-class to know if a sub-class has overridden a method?
You can compare whatever is in the class's __dict__ with the function inside the method you can retrieve from the object - the "detect_overriden" functionbellow does that - the trick is to pass the "parent class" for its name, just as one does in a call to "super" - else it is not easy to retrieve attributes from the parentclass itself instead of those of the subclass:
edit changed code to work fine with classmethods as well: if it detects a classmethod on the parent class, extracts the underlying function before proceeding.
-- Another way of doing this, without having to hard code the class name, would be to follow the instance's class (
self.__class__
) method resolution order (given by the__mro__
attribute) and search for duplicates of the methods and attributes defined in each class along the inheritance chain.You can use your own decorator. But this is a trick and will only work on classes where you control the implementation.
In reply to answer https://stackoverflow.com/a/9437273/1258307, since I don't have enough credits yet to comment on it, it will not work under python 3 unless you replace
im_func
with__func__
and will also not work in python 3.4(and most likely onward) since functions no longer have the__func__
attribute, only bound methods.EDIT: Here's the solution to the original question(which worked on 2.7 and 3.4, and I assume all other version in between):
And here's the output:
Not sure if this is what you're looking for but it helped me when I was looking for a similar solution.
It seems simplest and sufficient to do this by comparing the common subset of the dictionaries of an instance and the base class itself, e.g.:
Runs and gives: