GeneralBecos
GeneralBecos

Reputation: 2556

Python design: OOP

I'm trying to do something along these lines:

class A:

    def __init__( self, x=None, y=None ):
        self.x = x
        self.y = y

class B( A ):

     def do_something_in_Bs_context( self ):
         print "In B"

class C( A ):

    def do_something_in_Cs_context( self ):
        print "In C"


a = A(1,2)
b = B.do_something_in_Bs_context( a )
c = C.do_something_in_Cs_context( a )

As expected this code will generate this error:

TypeError: unbound method do_something_in_Bs_context() must be called with B instance as first argument (got A instance instead)

The underlying reason for this design is that A is a container of data ( say a table ) and B and C are a set of operations on A. Both B and C operate on the same data but are conceptually a distinct set of operations that can be performed on the same data. I could club all the operations in B and C inside A, but I want to create the separation in concepts. (As an example, on a table, I can perform different sets of operations which may be grouped into say Calculus or Trignometry. So A:Table, B: Calculus, C:Trignometry)

This reminded me of the Model-View-Controller paradigm with a slight twist.

I came up with the following solutions:

  1. B and C are implemented as conceptually different classes (a View/Controller) that maintain a reference to an instance of A and operate on that instance.
  2. Since B and C just group together methods on A, create modules with functions that operate on an instance of A.

I don't like either of these solutions much (2 slightly better than 1), but then I'm not sure if there is a better/cleaner/more pythonic way to solve this problem is. Any pointers?

Upvotes: 4

Views: 210

Answers (2)

Nicola Musatti
Nicola Musatti

Reputation: 18218

Move state in an additional class and make an instance of it an attribute of A:

class State(object):
    def __init__( self, x=None, y=None ):
        self.x = x
        self.y = y

class A(object):
    def __init__( self, state=None ):
        self.state = state

class B( A ):
    def __init__( self, state=None ):
        super(B, self).__init__(state)

    def do_something_in_Bs_context( self ):
        print self.state.x

class C( A ):
    def __init__( self, state=None ):
        super(C, self).__init__(state)

    def do_something_in_Cs_context( self ):
        print self.state.y

s = State(1, 2)
b = B(s)
c = C(s)
b.do_something_in_Bs_context()
c.do_something_in_Cs_context()

Upvotes: 1

Matt Fenwick
Matt Fenwick

Reputation: 49085

Here's how I understand the question: B and C are collections of functions that consume data of type A. What you want to do is group the functions logically.

I'd suggest doing one of the following:

  1. separate the functions into classes B and C that operate on A's -- this is a HAS-A relationship. The functions/methods could be static, if that's what you need
  2. separate the functions into modules B and C, creating top-level function definitions

I think inheritance would be a bad solution to this problem. I don't think there's an IS-A relationship.

Upvotes: 6

Related Questions