can a subclass method determine if called by superclass?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Jan 4 21:18:21 EST 2012


On Wed, 04 Jan 2012 15:37:55 -0800, Peter wrote:

> I am trying to create a subclass with slightly different functionality
> and use it with an existing code base i.e. there is already one or
> more modules that instantiate the current superclass and I want to
> just drop in this new class to replace it with no ripples up the line
> (so to speak). The new class implements some interface changes that
> can safely be hidden from the rest of the application.

This is *exactly* the idea behind subclassing. I don't understand your 
problem, can you explain more?

If you want to change behaviour of an object, you subclass it, then 
override or overload the methods you want to change. You certainly 
shouldn't be changing the superclass to recognise when it is being called 
from a subclass! That's completely the wrong approach -- you should put 
all the new behaviour in the new class.


# WRONG! Don't do this.

class Parent(object):
    def method(self, arg):
        if type(self) is not Parent:
            # Must be a subclass.
            print("Called from a subclass. But which one?")
        print("Doing method stuff.")

class Child(Parent):
    pass


# RIGHT! Do this instead.

class Parent(object):
    def method(self, arg):
        print("Doing method stuff.")

class Child(Parent):
    def method(self, arg):
        # Overload an existing method.
        print("Called from Child subclass.")
        super().method(arg)  # Python 3 only
        # Python 2 use: super(Child, self).method(arg)


If method() returns a result, you can capture the result of calling the 
superclass method and then modify it as needed. Or you can override the 
method completely, and not call the parent method() at all.

Now you can use Child() anywhere that you can use Parent and the caller 
shouldn't even notice. Or at least that is the idea behind subclassing, 
although it is possible to break it. You will be okay if the caller uses 
duck-typing, or isinstance checks, but not if they do exact type checks 
(which is almost always the wrong thing to do).

c = Child()

# Duck-typing works:
hasattr(c, 'method')  # returns True

# So do isinstance checks:
isinstance(c, Parent)  # returns True

# but this doesn't and defeats the purpose of having subclasses:
type(c) is Parent  # returns False, you shouldn't do this!


If the caller does do exact type checks, then almost certainly it should 
be considered a bug in their code and they should be beaten with a clue-
bat and told to use isinstance (good) or duck-typing (better still).


If I have misunderstood your problem, can you give a concrete (but 
simple) example of what you are trying to do?



-- 
Steven



More information about the Python-list mailing list