wkzhu
wkzhu

Reputation: 1660

Create two sets of classes with different inheritance

I have a base class Foo and another base class Bar.

I would like to create two sets of Baz classes (e.g., Baz1, ..., Baz20) such that for each N from 1 to 20, there's a BazN class that inherits from Foo, and also a BazN class that inherits from Bar. So I'd end up with 40 BazN classes, 20 of which are BazNFoo and 20 of which are type BazNBar.

What I have is the below snippet, which explicitly writes each BazN class twice, once inheriting from Foo and once from Bar. My question is, is there a programmatic way to do this writing each BazN class just once? My Baz classes are pretty long.

class Foo:
    def __init__(self):
        # code specific to Foo
    
class Bar:
    def __init__(self):
        # code specific to Bar

class Baz1Foo(Foo):
    def __init__(self):
        super().__init__()
        # code specific to Baz1

class Baz1Bar(Bar):
    def __init__(self):
        super().__init__()
        # code specific to Baz1

class Baz2Foo(Foo):
    ...

Upvotes: 1

Views: 121

Answers (1)

match
match

Reputation: 11070

You can create dynamic subclasses using type - however this is relatively advanced and just because it can be done this way, doesn't mean it's a good idea...

# Define a parent class
class Foo():
    def __init__(self):
        print("Init Foo")

    def foo(self):
        print("Method Foo")

# Create a dict to store the sub-classes in (could use globals() instead)
classes = {}
for i in range(2):
    # Create Foo0..Foo2
    classes[f'Foo{i}'] = type(
        f'Foo{i}',
        # Inherit from Foo
        (Foo,),
        # super() must be passed child class object in type construction
        # https://bugs.python.org/issue29944
        { "__init__": lambda self: super(self.__class__, self).__init__() }
    )

# Some proof it works...
for cls in classes.values():
    # Instantiate each class
    i = cls()
    # Print the class info (name)
    print(i.__class__)
    # Call the (inherited) foo method
    i.foo()

    ### OUTPUT:
    # Init Foo
    # <class '__main__.Foo0'>
    # Method Foo
    # Init Foo
    # <class '__main__.Foo1'>
    # Method Foo
    # Init Foo
    # <class '__main__.Foo2'>
    # Method Foo

Upvotes: 2

Related Questions