lars111
lars111

Reputation: 1313

Python OOP inherited classes

I would like to implement the following structure:

class Case(nx.Graph):   
    def __init__(self, case):       
        if case == 1:
            self = Case1()
        if case == 2:
            self = Case2()    

class Case1(Case):
    def __init__(self):
        super(Case1, self).__init__()
        print "Case1"

class Case2(Case):
    def __init__(self):
        super(Case2, self).__init__() 
        print "Case2"

For instance, if I create the following object:

graph = Case(1)

a new Object of the class Case1 should be created. In the __init__ of the class Case1 the super() fuction should call the __init__ function of the networkx.Graph().

If I run that code, the result should be a networkx.Graph object called "graph" and it should print Case1.

Upvotes: 1

Views: 115

Answers (3)

F1Rumors
F1Rumors

Reputation: 948

This is a classic Factory pattern. I would implement it using a static method as follows:

class Case(object):   

    @staticmethod
    def factory(case):
        if case == 1:
            return Case1()
        if case == 2:
            return Case2()
        raise NotImplementedError('Unknown case: %r'%case)

class Case1(Case):
    def __init__(self):
        super(Case1, self).__init__()
        print "Case1"

class Case2(Case):
    def __init__(self):
        super(Case2, self).__init__() 
        print "Case2"

You can extend as appropriate for args to pass to the initializer. IN usage, you might see something like the following:

c1 = Case.factory(1)
c2 = Case.factory(2)
print type(c1), type(c2)
Case.factory(3)

Output would look like this:

Case1
Case2
<class '__main__.Case1'> <class '__main__.Case2'>

Traceback (most recent call last):
  File "<string>", line 36, in <module>
  File "<string>", line 19, in factory
NotImplementedError: Unknown case: 3

Upvotes: 0

MSeifert
MSeifert

Reputation: 152577

One way of doing it is by not invoking __init__ for the subclasses but putting these in a seperate method, i.e. setup and rewriting the __class__ attribute:

class Case(object):   
    def __init__(self, case):
        # Maybe even call the init of the superclass:
        super(Case, self).__init__()
        # Do the setup that is common to all Cases:
        self.setup()
        # Change the class of the instance depending on your case:
        if case == 1:
            self.__class__ = Case1  # No () here!
        elif case == 2:
            self.__class__ = Case2
        else:
            raise ValueError()
        # Call the setup of the subclass
        self.setup()

    def setup(self):
        print('Setup of Case called.')


class Case1(Case):

    def setup(self):
        print('Setup of Case1 called.')

class Case2(Case):

    def setup(self):
        print('Setup of Case2 called.')

when I try to create a Case1:

a = Case(1)

it prints:

Setup of Case called.
Setup of Case1 called.

But there might even be proper (builtin-modules, packages) recipes for doing something like this.

Upvotes: 0

zondo
zondo

Reputation: 20336

When you say self = ..., you are just redefining self. You aren't changing it. To do what you want, use __new__ instead:

class Case(nx.Graph):
    def __new__(self, case):
        if case == 1:
            return Case1()
        elif case == 2:
            return Case2()
        else:
            raise ValueError("Invalid argument")

You really shouldn't do this, though. If you want a different instance for a different case, do it when you create the instance, but a class should not depend on its children in order to work.

Upvotes: 1

Related Questions