2012-02-09 17 views
5

I tienen una metaclase:metaclase error: tipo .__ init __() toma 1 o 3 argumentos

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

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

y una clase:

class MyClass(object): 
    __metaclass__ = MyMeta 

Cuando utilizo estos me sale el siguiente error:

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

¿Cuál es el problema, y ​​por qué type.__init__() toma una cantidad de argumentos con una precisión variable?

Respuesta

8

El problema es que en la actualización de python 2.5 a python 2.6 se modificó type.__init__(), por lo que ya no es necesario pasar cls. Por lo que simplemente hacer que el super llamada:

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

Otra solución es evitar la llamada super por completo y hacer esto (aunque es un poco menos agradable):

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

Y todo va a funcionar bien (en python > = 2.6).

En cuanto a por qué type.__init__() puede tomar diferentes números de argumentos, consulte the documentation. Es por lo que, además de usarlo como un constructor, puede llamar type(myobject) y ha de devolver el tipo de myobject:

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

Ver What is a metaclass in Python? para más información sobre metaclases y tipo.

+3

Tenga en cuenta que 'super (MyMeta, cls) .__ init__ (nombre, bases, dct)' es la forma * correcta * de hacerlo, incluso en 2.5 (y tan atrás como 2.2). El único caso en el que pase 'cls' ya que el primer argumento es' __new__', no con '__init__' (y eso no es específico de' type' o metaclasses tampoco). Lo que cambió es que 'type .__ init __()' dejó de tragar excepciones, muy parecido 'objeto .__ init __()'. –

+2

@ julio.alegria http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ –

+0

@HarleyHolcombe Sé que está permitido contestar su pregunta, pero ... ¿30 segundos? Significa que la respuesta estuvo lista incluso antes de publicar la pregunta, eso es un poco extraño – juliomalegria

Cuestiones relacionadas