Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamic class inheritance using super

I'm trying to dynamically create a class using type() and assign an __init__ constructor which calls super().__init__(...); however, when super() gets called I receive the following error:

TypeError: super(type, obj): obj must be an instance or subtype of type

Here is my code:

class Item():    
    def __init__(self, name, description, cost, **kwargs):
        self.name           = name
        self.description    = description
        self.cost           = cost
        self.kwargs         = kwargs

class ItemBase(Item):
    def __init__(self, name, description, cost):
        super().__init__(name, description, cost)

def __constructor__(self, n, d, c):
    super().__init__(name=n, description=d, cost=c)

item = type('Item1', (ItemBase,), {'__init__':__constructor__})
item_instance = item('MyName', 'MyDescription', 'MyCost')

Why is super() inside the __constructor__ method not understanding the object parameter; and how do I fix it?

like image 850
sadmicrowave Avatar asked Dec 07 '15 20:12

sadmicrowave


Video Answer


2 Answers

Here is how I solved the issue. I reference the type() method to dynamically instantiate a class with variable references as such:

def __constructor__(self, n, d, c, h):
    # initialize super of class type
    super(self.__class__, self).__init__(name=n, description=d, cost=c, hp=h)

# create the object class dynamically, utilizing __constructor__ for __init__ method
item = type(item_name, (eval("{}.{}".format(name,row[1].value)),), {'__init__':__constructor__})
# add new object to the global _objects object to be used throughout the world
self._objects[ item_name ] = item(row[0].value, row[2].value, row[3].value, row[4].value)

There may be a better way to accomplish this, but I needed a fix and this is what I came up with... use it if you can.

like image 82
sadmicrowave Avatar answered Oct 19 '22 02:10

sadmicrowave


Note the solution of sadmicrowave creates an infinite loop if the dynamically-created class gets inherited as self.__class__ will correspond to the child class.

An alternative way which do not have this issue is to assigns __init__ after creating the class, such as the class can be linked explicitly through closure. Example:

# Base class
class A():
  def __init__(self):
    print('A')

# Dynamically created class
B = type('B', (A,), {})

def __init__(self):
  print('B')
  super(B, self).__init__()

B.__init__ = __init__

# Child class
class C(B):
  def __init__(self):
    print('C')
    super().__init__()


C()  # print C, B, A
like image 43
Conchylicultor Avatar answered Oct 19 '22 00:10

Conchylicultor