Ben Chuanlong Du's Blog

It is never too late to learn.

Shadow Parent Methods in Python

Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!

Below is an example of shadowing a parent method in a child class.

In [27]:
class Animal:
    def __init__(self, name):
        self.name = name

    def sound(self):
        pass

    def get_name(self):
        return self.name


class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)

    def sound(self):
        return "Bark!"

    def sleep(self):
        return "Quiet."

    def __getattribute__(self, name):
        if name in ["get_name"]:
            raise AttributeError(name)
        else:
            return super().__getattribute__(name)

    def __dir__(self):
        return sorted(
            (set(dir(self.__class__)) | set(self.__dict__.keys())) - set(["get_name"])
        )

Animal

In [28]:
animal = Animal("whoever")
animal
Out[28]:
<__main__.Animal at 0x7f58845dc4f0>
In [29]:
[m for m in dir(animal) if not m.startswith("_")]
Out[29]:
['get_name', 'name', 'sound']
In [30]:
animal.get_name()
Out[30]:
'whoever'

Dog

In [31]:
dog = Dog("Jason")

Verify that dir(dog) does not show the shadowed method get_name.

In [32]:
[m for m in dir(dog) if not m.startswith("_")]
Out[32]:
['name', 'sleep', 'sound']

Verify that the method get_name is not accessible via an instance of Dog.

In [34]:
dog.get_name()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [34], in <cell line: 1>()
----> 1 dog.get_name()

Input In [27], in Dog.__getattribute__(self, name)
     22 def __getattribute__(self, name):
     23     if name in ["get_name"]: 
---> 24         raise AttributeError(name)
     25     else: 
     26         return super().__getattribute__(name)

AttributeError: get_name

Verify that other methods are accessible.

In [35]:
dog.sound()
Out[35]:
'Bark!'
In [36]:
dog.sleep()
Out[36]:
'Quiet.'

However, notice that even if the shadowed parent method get_name won't be seen using dir(dog), it still shows up by call dir(Dog).

In [22]:
[m for m in dir(Dog) if not m.startswith("_")]
Out[22]:
['get_name', 'sound']
In [ ]:
 

Comments