在 metaclass 中实例化刚刚创建的 class 会导致 RuntimeError ("super(): empty __class__ cell")
Instantiating a just-created class in a metaclass results in a RuntimeError ("super(): empty __class__ cell")
所以我有这个元class,我想用它来自动注册新组件,即一些基本组件class的子classes。注册新组件时,其 实例 应传递给处理该组件的 register_component() 函数。
Metaclass 代码(精简版):
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
问题是调用 new_class()
会导致错误 - 但并非对所有 class 都是如此。经过一些试验后,我意识到这只有在 subclass 在它自己的 __init__()
方法中调用 super().__init__()
时才会发生。
示例组件和基础class:
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'
我在这里做错了什么?阅读 this 我发现我可能不应该在 metaclass 的 __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
也许这行得通:
#!/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__()
所以我有这个元class,我想用它来自动注册新组件,即一些基本组件class的子classes。注册新组件时,其 实例 应传递给处理该组件的 register_component() 函数。
Metaclass 代码(精简版):
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
问题是调用 new_class()
会导致错误 - 但并非对所有 class 都是如此。经过一些试验后,我意识到这只有在 subclass 在它自己的 __init__()
方法中调用 super().__init__()
时才会发生。
示例组件和基础class:
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'
我在这里做错了什么?阅读 this 我发现我可能不应该在 metaclass 的 __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
也许这行得通:
#!/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__()