为啥我的元类实现失败并出现关于无法创建 NoneType 实例的 TypeError

Posted

技术标签:

【中文标题】为啥我的元类实现失败并出现关于无法创建 NoneType 实例的 TypeError【英文标题】:Why does my metaclass implementation fail with a TypeError about not being able to create NoneType instances为什么我的元类实现失败并出现关于无法创建 NoneType 实例的 TypeError 【发布时间】:2014-12-18 11:51:50 【问题描述】:

我有以下 Python 代码:

class MetaData(object):
    _md = 

class _ClassMeta(type):
    def __new__(cls, clsname, bases, dct):
        ncls = super(_ClassMeta, cls).__new__(cls, clsname, bases, dct)
        MetaData._md[clsname] = ncls

class Meta(object):
    __metaclass__ = _ClassMeta

class Test(Meta):
    pass

当我尝试执行它时,我得到了这个:

TypeError: Error when calling the metaclass bases
    cannot create 'NoneType' instances

class Test(Meta): 在线我不明白为什么。元类的__new__ 函数显然对 Meta 类调用得很好,但对派生的 Test 类却没有。

对于那些问“为什么”的人——我正在探索运行时类的注册和修改,比如 Django 和 SqlAlchemy 等 ORM 框架。这可能不是我最终生成代码的方式,但我仍然想知道为什么会出现 TypeError 异常。

【问题讨论】:

首先,这是 Python 2.x,对吧?元类是在 2.x 和 3.x 之间发生了巨大变化的事物之一,值得使用特定的标签…… 我已经添加了python-2.7标签,但是以后你应该自己做。 【参考方案1】:

您的问题很简单:__new__ 方法必须创建一个实例并返回它。你没有返回任何东西,所以它返回None

由于这是一个元类的__new__,这意味着它被调用来构造Meta 类对象。所以您刚刚将Meta 定义为None,而不是_ClassMeta 类型的类。这是一件非常有效的事情,因此那里没有错误,但是一旦您尝试对它做任何事情,例如Meta(),您就会得到一个关于NoneType 不可调用或类似的异常。

这包括对它进行子类化。你不能继承None,因为它不是一个类型。

【讨论】:

天啊!错误消息的原因是因为在为 Test 创建类时 Meta 为 None。是的,很简单,我不禁想到我花了多长时间盯着那个,不应该超过 30 秒。谢谢!当接受块计时器用完时我会接受

以上是关于为啥我的元类实现失败并出现关于无法创建 NoneType 实例的 TypeError的主要内容,如果未能解决你的问题,请参考以下文章

为啥一个类具有它的元类的属性?

django:为啥我们在 modelSerializer 中使用嵌套的元类?

深入理解Python中的元类---metaclass

如何创建可以为类提供实例数组并提供作用于所有类实例的“巫毒”实例的元类?

理解python的元类

Pyhton中的元类