【问题标题】:metaclass error: type.__init__() takes 1 or 3 arguments元类错误:type.__init__() 需要 1 或 3 个参数
【发布时间】:2012-03-02 10:56:51
【问题描述】:

我有一个元类:

class MyMeta(type):
    def __init__(cls, name, bases, dct):
        # Do something
        ...

        return super(MyMeta, cls).__init__(cls, name, bases, dct)

还有一个班级:

class MyClass(object):
    __metaclass__ = MyMeta

当我使用这些时,我得到以下错误:

TypeError: Error when calling the metaclass bases
    type.__init__() takes 1 or 3 arguments

有什么问题,为什么type.__init__() 采用精确可变数量的参数?

【问题讨论】:

    标签: python python-2.x metaclass


    【解决方案1】:

    问题在于,在从 python 2.5 升级到 python 2.6 时,type.__init__() 已更改,因此您不再需要传入cls。所以只需拨打super 电话:

    return super(MyMeta, cls).__init__(name, bases, dct)
    

    另一种解决方案是完全避免 super 调用并执行此操作(尽管它不太好):

    return type.__init__(cls, name, bases, dct)
    

    一切都会正常运行(在 python >= 2.6 中)。

    关于为什么type.__init__() 可以接受不同数量的参数,请查看the documentation。这样除了将其用作构造函数外,您还可以调用type(myobject),它将返回myobject 的类型:

    >>> number = 1
    >>> type(number)
    <type 'int'>
    >>> type('my string')
    <type 'str'>
    

    有关元类和类型的更多信息,请参阅What is a metaclass in Python?

    【讨论】:

    • 请注意super(MyMeta, cls).__init__(name, bases, dct) 是这样做的正确 方式,即使在 2.5 中(以及早在 2.2 中)。您传递 cls 的唯一情况因为第一个参数是__new__,而不是__init__(这也不是特定于type或元类。)改变的是type.__init__()停止吞咽异常,就像object.__init__()一样。
    • @HarleyHolcombe 我知道回答你的问题是允许的,但是...... 30 秒?这意味着即使在您发布问题之前答案就已经准备好了,这有点奇怪
    • @julio.alegria Google 什么也没显示,在为 SO 写一个好问题时,我遇到了解决方案,因此决定为未来的搜索者写两个。
    猜你喜欢
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 2016-06-07
    • 2012-10-08
    • 1970-01-01
    • 2018-03-29
    相关资源
    最近更新 更多