percusse
percusse

Reputation: 3106

Python class inheritance design: Pretend to look like a duck but don't quack

I've searched for this for a few hours today but didn't get a recent and satisfactorily definitive answer.

Suppose we have two particular classes that have both overlapping method names and specific individual methods. Getting rid of the unnecessary parts let's work with the following classes.

class A():
    def __init__(self, a_arg1, a_arg2):
        self.a_arg1 = a_arg1
        self.a_arg2 = a_arg2

    @property
    def gimme_1(self):
        return self.a_arg1

    @property
    def gimme_2(self):
        return self.a_arg2

    @property
    def prop(self):
        return 'A'

and also

class B():
    def __init__(self, b_arg1, b_arg2, b_arg3):
        self.b_arg1 = b_arg1
        self.b_arg2 = b_arg2
        self.b_arg3 = b_arg3

    @property
    def give_1(self):
        return self.b_arg1

    @property
    def give_2(self):
        return self.b_arg2

    @property
    def give_3(self):
        return self.b_arg3

    @property
    def prop(self):
        return 'B'

My goal is to make a third class that can morph into one of these, namely, it will have all the methods that these two have and act as if it is one of them whichever is requested. That's the motivation for the title of the question.

class C(A, B):
    def __init__(self, some_list):
        self.some_list = some_list

    @property
    def gimme_1(self):
        return self.some_list[0]

    @property
    def gimme_2(self):
        return self.some_list[1]

    @property
    def give_1(self):
        return self.some_list[0] ** 2

    @property
    def give_2(self):
        return self.some_list[1] ** 2

    @property
    def give_3(self):
        return self.some_list[2]

    @property
    def prop(self):
        return 'C'

Concrete questions:

  1. Do we have to initialize the parents for this particular instance? If yes how should the super() be used.
  2. This would really help me getting away with isinstance(x, A) or isinstance(x, B) type of querying. Is there any best practice that discourages such usage? Notice that the Pythonic duck typing is really not so relevant for me in my case. There are a lot of branching necessarily happening for different computational algorithms. Hence I'm really using classes as data-bundling containers but not using them as state recorders. In other words, there is hardly ever change in their instance data. But their data is used in different branches depending on which class they are. Therefore getting the right kind of object is essential for me.

Upvotes: 0

Views: 205

Answers (1)

Patrick Haugh
Patrick Haugh

Reputation: 61032

Instead of rewriting the methods, why not take advantage of the benefits of inheritance? Let the parent __init__s take care of setting up instance values, and let them provide the method implementations.

class C(A, B):
    def __init__(self, arg1, arg2, arg3):
        A.__init__(self, arg1, arg2)
        B.__init__(self, arg1**2, arg2**2, arg3)

    @property
    def prop(self):
        return 'C'

Upvotes: 2

Related Questions