使用 super 的动态类继承

sad*_*ave 8 inheritance object superclass python-3.x

我正在尝试使用type()并分配一个__init__调用的构造函数来动态创建一个类super().__init__(...);但是,当super()被调用时,我收到以下错误:

TypeError: super(type, obj): obj must be an instance or subtype of type
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

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')
Run Code Online (Sandbox Code Playgroud)

为什么super()__constructor__方法内部不理解对象参数;我该如何解决?

Con*_*tor 9

解决方案1:使用cls = type('ClassName', ...)

self.__class__请注意,如果动态创建的类被继承为对应于子类,则 SadMicrowave 的解决方案会创建无限循环。

另一种不存在此问题的方法是__init__在创建类之后进行赋值,例如可以通过闭包显式链接该类。例子:

# 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
Run Code Online (Sandbox Code Playgroud)

解决方案 2:使用MyClass.__name__ = 'ClassName'

动态创建类的另一种方法是在函数内定义一个类,然后重新分配__name____qualname__属性:

class A:
  
  def __init__(self):
    print(A.__name__)


def make_class(name, base):

  class Child(base):
    def __init__(self):
      print(Child.__name__)
      super().__init__()

  Child.__name__ = name
  Child.__qualname__ = name
  return Child


B = make_class('B', A)


class C(B):
  
  def __init__(self):
    print(C.__name__)
    super().__init__()

C()  # Display C B A
Run Code Online (Sandbox Code Playgroud)


sad*_*ave 6

这是我解决问题的方法。我引用了type()使用变量引用动态实例化类的方法,如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

可能有更好的方法来实现这一点,但我需要一个修复程序,这就是我想出的……如果可以,请使用它。