Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

metaclass error: type.__init__() takes 1 or 3 arguments

I have a metaclass:

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

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

and a class:

class MyClass(object):
    __metaclass__ = MyMeta

When I use these I get the following error:

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

What's the problem, and why does type.__init__() take a precisely variable number of arguments?

like image 686
Harley Holcombe Avatar asked Feb 09 '12 22:02

Harley Holcombe


1 Answers

The problem is that in the upgrade from python 2.5 to python 2.6 type.__init__() was changed so that you are no longer required to pass in cls. So simply make the super call:

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

Another solution is to avoid the super call altogether and do this (although it's a little less nice):

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

And everything will work fine (in python >= 2.6).

As to why type.__init__() can take differing numbers of arguments, check out the documentation. It's so that as well as using it as a constructor, you can call type(myobject) and it will return the type of myobject:

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

See What is a metaclass in Python? for more information on metaclasses and type.

like image 60
Harley Holcombe Avatar answered Sep 21 '22 00:09

Harley Holcombe