flamenco
flamenco

Reputation: 2840

How to switch between methods inherited from multiple classes in Python

I would like to build a class which inherits from a dict and some other classes.

Based on a key of someDict (initial dictionary), Third class should inherit either from First or from Second.

Here is a basic example:

class First(object):

  def first_action(self):
      print "first_action"


class Second(object):

  def second_action(self):
      print "second_action"


class Third(dict, First, Second):
   """This is not running code
      but, rather, an example of desired functionality.
   """
   if "x" == someDict["some_key"]:
       third_action == First.first_action()
       print third_action
   else:
       third_action == Second.second_action()
       print third_action

A desired output:

obj = Third()
obj.third_action()
'first_action'  # <- Should print this value if dict["some_key"] = "x"
'second_action' # <- if someDict["some_key"] != "x"

For more general case Third class, based on the value of a key of someDict, should switch between methods belonging to First or Second. If action is a method of Third, it should switch between first_action or second_action.

Any suggestion is appreciated!

Upvotes: 1

Views: 1683

Answers (3)

Vadim Pushtaev
Vadim Pushtaev

Reputation: 2353

General case

As long as some_key can be changed, the inheritance is not what you want here. Despite of the fact you technically could make this kind of chameleon class, you should definitely avoid this.

Basically, you should explicitly override all chameleon methods and call another one within, according to your condition ("x" == someDict["some_key"]).

You also may have a look at decorator pattern. Your object may store the action and apply different decorators according to the condition. Once again, as far as I understand the question, the condition may vary, hence must be checked every single time (and this means you should override all methods that depend on this condition).

You also may want to override all methods that could change some_key instead of all chameleon ones: it allows to cache the result of "x" == someDict["some_key"] while some_key is not changing.

Predefined dictionary case

In comment section you say your dictionary is predefined. In this case, you should just define two different classes:

class ThirdA(dict, First)
class ThirbB(dict, Second)

Also you need some factory to choose between ThirdA and ThirdB for you.

class ThirdFactory(object):
    @classmethod
    def create(cls, dictionary):
        if "x" == dict["some_key"]:
            return ThirdA(dictionary)
        else:
            return ThirdB(dictionary)

(Factory method also works here, as long as you have suitable class to place it.)

So now you can just

my_object = ThirdFactory.create(dict(some_key='x'))

Mind that the class of the object will never change. If you want it to change, view the first part of my answer.

P. S. Don't name your dictionary dict, that's the name of the type.

Upvotes: 3

shaktimaan
shaktimaan

Reputation: 1857

While assigning the function from first or second class you dont need to put parenthesis. And also I dont understand what are you doing in this line

if "x" == dict["some_key"]

Is dict some predefined dictionary then you should not use the name "dict" as it overrides the default builtin dict keyword. Assuming it is a predefined dictionary (let us name it someDict). This shoud do.

class Third(dict, First, Second):
   if "x" == someDict["some_key"]:
       third_action = First.first_action
       print action
   else:
       third_action = Second.second_action
       print action

Upvotes: 1

Stephen Lin
Stephen Lin

Reputation: 4912

first_action or second_action are not class methods so that you can not call them that way. You could write like this:

class First(object):

  def first_action(self):
      print "first_action"

class Second(object):

  def second_action(self):
      print "second_action"

# you have to change name of that dictionary from dict to my_dict since dict is the name of a built-in class
class Third(my_dict, First, Second):
   """This is not running code
      but, rather, an example of desired functionality.
   """
   # define a function named third_action to achieve this
   def third_action(self):
       if "x" == my_dict["some_key"]:
           # you have to call instance method this way
           third_action == self.first_action()
           print action
       else:
           third_action == self.second_action()
           print action

You can get your expected output through this way.

Upvotes: 1

Related Questions