Batman Batman - 10 days ago 7
Python Question

Easy Way To Overload All Methods of a Class

Somewhat unrealistic hypothetical situation, but:

Say I have a new class

Foo
that I've written which constructs an object which is used as input argument for an existing class
Bar
.
Foo
is designed to add some functionality to
Bar
, but I do not want it to interfere with any of my existing jobs that already run. E.g. I want to be very careful that I'm not affecting any of my existing jobs that use
Bar
, because the data that the existing jobs write should be continuous/consistent.

Let's say that for whatever reason, I can't add a kwarg
foo=None
to the constructor for
Bar
. Or I could, but it would be a huge hassle. What I want to do give it an instance of
Foo
that does nothing.

Is there a really straight forward way to overload all the methods of
Foo
so that they do nothing? Or would I be forced to code each method like

class DummyFoo(Foo):
def __init__(*args, **kwargs):
pass

def method1(*args, **kwargs):
pass

def method2(*args, **kwargs):
pass


etc?

Answer

The easiest way is probably to override __getatrribute__.

class Foo:
    blar = 1
    def bar(self):
        print("It's a bar! Scary Bar!")


class DummyFoo(Foo):
    def __getattribute__(self, item):
        if callable(getattr(super(), item)):
            return lambda *x : None
        return None


dummy_foo = DummyFoo()
dummy_foo.bar()  # Should do nothing.
print(dummy_foo.blar)

Note, this will resolve ANY attributes, not just the ones on Foo. If you need to only limit to attributes that are part of Foo, you can do this:

class Foo:
    blar = 1

    def bar(self):
        print("It's a bar! Scary Bar!")


class DummyFoo(Foo):
    def __getattribute__(self, item):
        if item not in super().__dict__:
            raise AttributeError
        if callable(getattr(super(), item)):
            return lambda *x: None
        return None


dummy_foo = DummyFoo()
print(dummy_foo.bing())  # Raises an AttributeError.
Comments