Pdeuxa
Pdeuxa

Reputation: 699

Metaclass with inheritence

I need to create class on the go thus I am oriented to metaclass.

I have a main class with methods and __init__. I need to create class from this main class, thus I do the following:

class main_class:
    def __init__(self, val1, val2):
      self.foo=val1
      self.bar=val2

my_new_class= type('new_class', (main_class,),{'foo':'new_foo'})
m = my_new_class("hello", world")
print(m.foo)
>>> hello

In my understanding, the init method from the main_class could overdrive the attributes of my_new_class. I didn't find a way how to superseed the init from main_class.

I would like to do the following but without hardcoding the class :

class main_class:
    def __init__(self, val1, val2):
      self.foo=val1
      self.bar=val2

class new_class(main_class):
    def __init__(self, val1, val2, val3):
        super(main_class, self).__init__(val1=val1, val2=val2):
        self.foo=val3

Upvotes: 1

Views: 51

Answers (2)

salt-die
salt-die

Reputation: 854

You could get the desired behavior with a metaclass using the __call__ dunder:

class MyMeta(type):
    def __call__(cls, val1, val2, val3):
        return super().__call__(val3, val2)

class new_class(main_class, metaclass=MyMeta):
    pass

Upvotes: 0

AKX
AKX

Reputation: 168834

There are no metaclasses (aside from the built-in type) in your example.

However, you're misunderstanding what the third argument to type() does.

new_class = type('new_class', (main_class,), {'foo':'new_foo'})

is nearly equivalent to

class new_class(main_class):
    foo = 'new_foo'

– that is, it sets a class-level variable, and doesn't touch constructors at all.

Either way, you can also just define a class within a function, if it helps:

def make_class(val3_value):
    class new_class(main_class):
        def __init__(self, val1, val2, val3=val3_value):
            super().__init__(val1=val1, val2=val2)
            self.val3 = val3
    return new_class

Upvotes: 1

Related Questions