2

I am having a parent class A with few classes inheriting from it (B,C,...).

I have some function is_class_A that is implemented in A, and I want to override it in B and C in the same way.

Let say:

class A:
    def is_class_A():
        print("We are in class A")

class B(A):
    def is_class_A():
        print("Nope")

class C(A):
    def is_class_A():
        print("Nope")

Take in mind both functions that implement in class A and in the others, are long, and more complicate.

2 solutions I came in my mind to avoid the duplication in B, C implementation:

Using in class C:

def is_class_A():
    return B.is_class_A()

I am not sure how this will be functional, because an object of C is not an object of B. And I don't pass here any self, so I don't see how this will work, maybe something similar can?

Next solution is using another heritage:

class C(B)

This won't work always, since not always possible (if they have different attributes) and might not fit the design purpose.

My best attempt so far is to use another class:

class BC(A):
    def is_class_A():
        print("Nope")

class B(BC):
    pass

class C(BC):
    pass

What do you think? Some more ideas? Maybe something more technical that won't involve with the program design?

Thanks.

3
  • I would consider your first two solutions as bad because they mix functionality from classes that are not related hierarchy-wise, as you expressed ("might not fit the design purpose"). The intermediate class BC is not a bad idea as long as your class hierarchy does not get too deep. As long as you do not introduce one hierarchy level for each common functionality, it should be fine. You also may also look at multiple inheritance in Python. Commented Jun 29, 2021 at 11:22
  • I am familiar with multiple inheritance. You suggest to have a new class both B,C inherent in it, and implement it there? but in my function I may use many attributes that A have.. sounds like getting complicated Commented Jun 29, 2021 at 11:27
  • You can define your isClassA override in a separate class Z, then use class B(Z, A): .... Note that Z has to come first to ensure that Z.isClassA is used in preference to A.isClassA. I'm not sure if I actually like this idea, though; mix-ins usually add new functionality rather than overriding existing functionality. I think I would go with the intermediate BC class as well. I don't know that you can really make the proper design decision based on this example, though: it's too abstract. Commented Jun 29, 2021 at 11:30

1 Answer 1

2

One option is to define the alternate method once at the global scope, then do direct class attribute assignment.

class A:
    def is_class_A(self):
        print("We are in class A")


def alt_is_class_A(self):
    print("Nope")


class B(A):
    is_class_A = alt_is_class_A


class C(A):
    is_class_A = alt_is_class_A


class D(A):
    pass  # No override

The assignment could also be handled by a decorator:

def mod_it(cls):
    cls.is_class_A = alt_is_class_A


@mod_it
class B(A):
    pass


@mod_it
class C(A):
    pass


# No override
class D(A):
    pass

or via A.__init_subclass__:

class A:
    def is_class_A(self):
        print("We are in class A")

    def __init_subclass__(cls, is_class_A=None):
        super().__init_subclass__()
        if is_class_A is not None:
            cls.is_class_A = is_class_A


def alt_is_class_A(self):
    print("Nope")


class B(A, is_class_A=alt_is_class_A):
    pass


class C(A, is_class_A=alt_is_class_A):
    pass


# No override 
class D(A):
    pass
Sign up to request clarification or add additional context in comments.

4 Comments

If I wish to use some attributes in the function, how would that work with global functions?
Attributes are accessed via the first argument, the same as if the function were declared inside the class statement.
A method is just a class attribute with a value of type function, classmethod, or staticmethod. (The thing that actually gets called is the result of the attribute's __get__ method, per the descriptor protocol; it doesn't really matter where the attribute value is actually defined, as long as you aren't using non-local variables in the body of the function.)
Its a bit strange to use a global function in a complicated very OO program, but it can work without involving in the design.

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.