Martin
Martin

Reputation: 130

Inherit dynamic object in python

I want to create a sub class "sub()" that can inherit either object "A(object)" or object "B(object)".

The following works for this:

class A(object):
    def __init__(self):
        print "Class A was inherited"


class B(object):
    def __init__(self):
        print "Class B was inherited"


class sub(A if inh==A else B):
    def __init__(self,inh):
        if inh==A:
            A.__init__(self)
        else:
            B.__init__(self)

However, "inh" is not a defined parameter when I construct my "sub()". I want to be able to construct my "sub()" with an argument "inh" that initialize either "A(object)" or "B(object)".

So that:

my_object = sub(inh = A)

will give me:

Class A was inherited

And that:

my_object = sub(inh = B)

will give me

Class B was inherited

My problem is, how do I pass "inh" to the constructor "sub()" so it can choose the right object to inherit?

Upvotes: 0

Views: 208

Answers (2)

bruno desthuilliers
bruno desthuilliers

Reputation: 77952

Immortal's solution, while basically right, has a drawback: each call to Sub() will yield a new class, so things like isinstance() or class identity test will break. A solution to this is to keep a mapping of already created classes:

_CLSMAP = {}

def Sub(base, *args, **kw):
    if base not in _CLSMAP:
        class Sub(base):
            def __init__(self, *args, **kw):
                super(sub, self).__init__(*args, **kw)
    _CLSMAP[base] = Sub
    return _CLSMAP[base](*args, **kw)

Upvotes: 2

immortal
immortal

Reputation: 3188

It would seem to me that what you want is a generator/factory function that will construct and return a class instance as you'd wish. For that, you can use python's ability to define classes and functions within functions, so that your definition of class sub will be done in the scope of the factory function, like this:

def Sub(inh=object):
    class sub(inh):
       def __init__(self):
           super(sub, self).__init__()
    return sub()

You can now pass the desired subclass to your generator function and get an instantiated instance of the desired type.

Run output:

>>> def Sub(inh=object):
...     class sub(inh):
...        def __init__(self):
...            super(sub, self).__init__()
...     return sub()
...
>>> class A(object):
...     def __init__(self):
...         print "Class A was inherited"
...
>>>
>>> class B(object):
...     def __init__(self):
...         print "Class B was inherited"
...
>>>
>>> Sub(A)
Class A was inherited
<__main__.sub object at 0x014E4970>
>>> Sub(B)
Class B was inherited
<__main__.sub object at 0x014E49F0>
>>>

is as desired.

Upvotes: 1

Related Questions