在元类中实例化一个刚刚创建的类会导致RuntimeError("super():empty __class__ cell")

pla*_*mut 6 python metaclass

所以我有这个元类,我想用它来自动注册新组件,即一些基础组件类的子类.注册新组件时,应将其实例传递给处理该组件的register_component()函数.

元类代码(精简版):

class AutoRegisteredMeta(type):
    def __new__(metacls, name, bases, attrs):

        # ... (omitted) check if "name" has already been registered ...

        new_class = super().__new__(metacls, name, bases, attrs)
        register_component(name, new_class())  # RuntimeError(super(): empty __class__ cell)
        return new_class
Run Code Online (Sandbox Code Playgroud)

问题是调用new_class()导致错误 - 但不是所有类.经过一些实验后,我意识到只有在子类调用super().__init__()自己的__init__()方法时才会发生这种情况.

示例组件和基类:

class BaseComponent(metaclass=AutoRegisteredMeta):
    def __init__(self):
        # do some work here ...

class ComponentFoo(BaseComponent):
    def __init__(self):
        super().__init__()  # <--- RuntimeError occurs here
        self.foo = 'bar'
Run Code Online (Sandbox Code Playgroud)

我在这做错了什么?读这个我发现我可能不应该做的实例在metaclass'es __new__()或者__init__(),对不对?这可能会以某种方式被规避吗?

另外,外行人的一些解释是好的,我不太了解CPython实现的内部结构.

提前致谢!

(FWIW,我使用Python 3.3.6,Ubuntu)


编辑:我正在添加请求的最小示例,您可以直接运行它并自己查看错误.

#!/usr/bin/env python3


class AutoRegisteredMeta(type):
    def __new__(metacls, name, bases, attrs):
        new_class = super().__new__(metacls, name, bases, attrs)
        new_class()  # <--- RuntimeError can occur here
        return new_class


class BaseComponent(metaclass=AutoRegisteredMeta):
    def __init__(self):
        print("BaseComponent __init__()")


class GoodComponent(BaseComponent):
    def __init__(self):
        print("GoodComponent __init__()")


class BadComponent(BaseComponent):
    def __init__(self):
        print("BadComponent __init__()")
        super().__init__()  # <--- RuntimeError occurs because of this
Run Code Online (Sandbox Code Playgroud)

svs*_*svs 4

也许这有效:

#!/usr/bin/env python3


class AutoRegisteredMeta(type):
    def __new__(metacls, name, bases, attrs):
        new_class = super().__new__(metacls, name, bases, attrs)
        new_class()
        return new_class


class BaseComponent(metaclass=AutoRegisteredMeta):
    def __init__(self):
        print("BaseComponent __init__()")


class GoodComponent(BaseComponent):
    def __init__(self):
        print("GoodComponent __init__()")


class BadComponent(BaseComponent):
    def __init__(self):
        print("BadComponent __init__()")
        super(self.__class__, self).__init__()
Run Code Online (Sandbox Code Playgroud)