2

I am looking for advice on how to construct some project I gonna work on.

I got a base class, with some methods.

class Base(object):
  def method1(self):
    # some code
  def method2(self):
    # some code
  def method3(self):
    # some code
... and some other methods

For my project, I cannot modify the Base class, and I must inherent from it in order to apply my project requirements.

I have several requirement that might be enabled or not. Depending on a given configuration. I.e. I'd like to be able to override either method1(), method2(), method3() or any combination of them.

One alternative is to construct several inheriting classes.

class Child1(Base):
  def method1(self): 
    # some code

class Child2(Base):
  def method2(self): 
    # some code

class Child3(Base):
  def method3(self): 
    # some code

And then maybe use multiple inheritance to apply any composition of them. However this approach wouldn't scale well for covering all possible combinations.. (e.g. what happens if I will have Child4()? )

Another alternative is just having a single inheritance class and use if clauses to select whether to call the super method or apply the derived behavior.

class Child(Base):
  def method1(self): 
    if not self.override1:
      # call super
    else:
      # some code

  def method2(self): 
    if not self.override2:
      # call super
    else:
      # some code

  def method3(self): 
    if not self.override3:
      # call super
    else:
      # some code

I am more in favor on this alternative, however I feel there got to be a better OO approach for doing this.

Any thoughts or suggestions?

Thanks a lot

PS: I am constrained to python 2.7, and since I plan to share the code, I rather have a solution that is easy to understand by an average python programmer (and not only by advanced programmers).

1
  • Question is probably too broad. If the extent of the modification causes an instance to behave significantly different than instances without that modification - to the point that it can be considered a different thing, albeit related, then I would say that the your last solution is incorrect and you probably need the multiple inheritance/mixin approach. Commented Dec 9, 2016 at 1:00

2 Answers 2

2

I like the first choice it seems manageable, no code duplication:

class A:
    def one(self):
        return 'one |'
    def two(self):
        return 'two |'
    def three(self):
        return 'three |'
    def four(self):
        return 'four |'

class B(A):
    def one(self):
        return 'one foo |'

class C(A):
    def two(self):
        return 'two foo |'

class D(A):
    def three(self):
        return 'three foo |'

class BC(B, C):
    pass
class CD(C, D):
    pass
class BD(B, D):
    pass

Now you have seven things to choose from. If needed you can easily tell what kind of thing it is at run-time:

>>> bc = BC()
>>> isinstance(bc, A)
True
>>> isinstance(bc, CD)
False
>>> isinstance(bc, BC)
True

And you'll probably find out you forgot something and it is easy to add:

#oops now I need this
class X(A):
    def four(self):
        pass
# and this $#%^!*
class B1(A):
    def one(self):
        return 'one bar |'
Sign up to request clarification or add additional context in comments.

Comments

1

Keep in mind that class definitions are executed code. You could conditionally define or ignore a method in your child class:

class Child(Base):
    if something:
        def method1(self, etc):
            pass

Here's an example. Note that setting the condition has to happen before the class definition - this is not a dynamic parameter:

#!python3
import sys

special = False

if "--special" in sys.argv:
    special = True


class Base:
    def method1(self):
        print("Base method1")


    def method2(self):
        print("Base method2")

class Child(Base):
    def method3(self):
        print("Child method3")

    if special:
        def method1(self):
            print("Child method1")


ch = Child()
ch.method1()
ch.method2()
ch.method3()

Output is:

$ python test.py --special
Child method1
Base method2
Child method3

$ python test.py
Base method1
Base method2
Child method3

2 Comments

Nice! So it means I can only base the condition on sys.argv? Or there's another alternative?
There's definitely other alternatives. I based the condition on argv because it's a demo. You can base it on any other condition you want, as long as you can finalize the value before you define the class. For that matter, you could put the class definition inside a function, and call it to return the class...

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.