0

I have a base class which is inherited from by multiple classes. In the child classes, I want to make a method from the base class uncallable; so I'm using __getattribute__ to raise an error if they are tried from the child class. Dummy example below:

class Base(object):
    def f1():
        return 1

    def f2():
        return 2

    def f3():
        return 3


class Child1(Base):
     def __getattribute__(self, name):
        if name == 'f1':
            raise AttributeError(name)
        else:
            return super(Child1, self).__getattribute__(name)


class Child2(Base):
     def __getattribute__(self, name):
        if name == 'f2':
            raise AttributeError(name)
        else:
            return super(Child2, self).__getattribute__(name)


class Child3(Base):
     def __getattribute__(self, name):
        if name == 'f3':
            raise AttributeError(name)
        else:
            return super(Child3, self).__getattribute__(name)

So in this example, I don't want to be able to call f1 from Child1, f2 from Child2, and f3 from Child3.

Is there a way to re-write this that doesn't have so much code duplication and child classes just inherit the method? This is what I tried, but it first runs into recursion issues because the call to self.blocked_methods in and of itself calls __getattribute__. I imagine there are other issues but can't get past that one.

class Base(object):
    blocked_methods = []

    def f1():
        return 1

    def f2():
        return 2

    def f3():
        return 3

    def __getattribute__(self, name):
        if name in self.blocked_methods:
            raise AttributeError(name)
        else:
            return super(Child3, self).__getattribute__(name)


class Child1(Base):
     blocked_methods = ['f1']


class Child2(Base):
     blocked_methods = ['f2']


class Child3(Base):
     blocked_methods = ['f3']

3
  • "In certain classes, I want to make a method from the base class uncallable" You understand that this is explicitly the opposite of what inheritance is supposed to be for, yes? Commented Sep 10, 2020 at 20:08
  • 1
    This suggests that Base is not the appropriate base class for any of the three child classes. Consider defining separate mixin classes for each of the three methods instead. Commented Sep 10, 2020 at 20:09
  • Thanks @chepner, I'll look into mixins for a better design Commented Sep 10, 2020 at 20:09

1 Answer 1

1

Use multiple mix-in classes instead.

class Method1:
    def f1(self):
        return 1

class Method2:
    def f2(self):
        return 2

class Method3:
    def f3(self):
        return 3

class Child1(Method2, Method3):
    pass

class Child2(Method1, Method3):
    pass

class Child1(Method2, Method2):
    pass

It's not terribly scalable, but it's better than trying to subtract functionality from a class.

Sign up to request clarification or add additional context in comments.

1 Comment

This looks like the best approach for what I'm after, there would only be 3-4 mix-in classes. This actually works perfectly as now I can isolate and group functions specific to that mix-in.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.