“MetaClass”, “__new__”, “cls” y “super”: ¿cuál es el mecanismo exactamente?

He leído mensajes como estos:

  1. ¿Qué es una metaclase en Python?
  2. ¿Cuáles son sus casos de uso (concretos) para metaclases en Python?
  3. El Super de Python es ingenioso, pero no puedes usarlo

Pero de alguna manera me confundí. Muchas confusiones como:

¿Cuándo y por qué tendría que hacer algo como lo siguiente?

# Refer link1 return super(MyType, cls).__new__(cls, name, bases, newattrs) 

o

 # Refer link2 return super(MetaSingleton, cls).__call__(*args, **kw) 

o

 # Refer link2 return type(self.__name__ + other.__name__, (self, other), {}) 

¿Cómo funciona super realmente?

¿Qué es el registro de clase y la falta de registro en link1 y cómo funciona exactamente? (Pensé que tiene algo que ver con singleton . Puede que esté equivocado, al ser de fondo C. Mi estilo de encoding sigue siendo una mezcla de funcional y OO).

¿Cuál es el flujo de la instanciación de clase (subclase, metaclase, super, tipo) y la invocación de métodos (

 metaclass->__new__, metaclass->__init__, super->__new__, subclass->__init__ inherited from metaclass 

) con código de trabajo bien comentado (aunque el primer enlace está bastante cerca, pero no habla de la palabra clave cls, super (..) y registro). Preferiblemente un ejemplo con herencia múltiple.

PD: hice la última parte como código porque el formato de desbordamiento de stack estaba convirtiendo la metaclass->__new__ texto metaclass->__new__ a metaclass-> new

¡Bien, has introducido algunos conceptos en la mezcla aquí! Voy a sacar algunas de las preguntas específicas que tiene.

En general, entendiendo super, el MRO y las metclasses se hacen mucho más complicados porque ha habido muchos cambios en esta área difícil en las últimas versiones de Python.

La propia documentación de Python es una muy buena referencia, y está completamente actualizada. Hay un artículo de IBM developerWorks que está bien como introducción y tiene un enfoque más basado en tutoriales, pero tenga en cuenta que tiene cinco años y pasa mucho tiempo hablando sobre los enfoques de estilo más antiguo para las metaclases.

super es la forma en que se accede a las superclases de un objeto. Es más complejo que (por ejemplo) la super palabra clave de Java, principalmente debido a la herencia múltiple en Python. Como lo explica Super Considered Harmful , el uso de super() puede hacer que implemente que use una cadena de superclases, cuyo orden se define en la Orden de resolución de métodos (MRO).

Puede ver el MRO para una clase fácilmente invocando mro() en la clase (no en una instancia). Tenga en cuenta que las meta-clases no están en la jerarquía de superclases de un objeto.

La descripción de Thomas de las meta-clases aquí es excelente:

Una metaclase es la clase de una clase. Al igual que una clase define cómo se comporta una instancia de la clase, una metaclase define cómo se comporta una clase. Una clase es una instancia de una metaclase.

En los ejemplos que da, esto es lo que está pasando:

  1. La llamada a __new__ está __new__ hasta la próxima cosa en el MRO. En este caso, super(MyType, cls) se resolvería para type ; type.__new__ llamada type.__new__ permite a Python completar sus pasos normales de creación de instancias.

  2. Este ejemplo usa metaclases para imponer un singleton. Está anulando __call__ en la metaclase, de modo que cada vez que se crea una instancia de clase, la intercepta y puede omitir la creación de la instancia si ya hay una (almacenada en cls.instance ). Tenga en cuenta que anular __new__ en la metaclase no será lo suficientemente bueno, porque solo se llama al crear la clase . Sin __new__ reemplazar a __new__ en la clase funcionaría.

  3. Esto muestra una manera de crear dinámicamente una clase. Aquí está agregando el nombre de la clase suministrada al nombre de la clase creada, y también lo está agregando a la jerarquía de clases.

No estoy exactamente seguro de qué tipo de ejemplo de código está buscando, pero aquí hay una breve que muestra las metaclases, la herencia y la resolución de métodos:

 class MyMeta(type): def __new__(cls, name, bases, dct): print "meta: creating %s %s" % (name, bases) return type.__new__(cls, name, bases, dct) def meta_meth(cls): print "MyMeta.meta_meth" __repr__ = lambda c: c.__name__ class A(object): __metaclass__ = MyMeta def __init__(self): super(A, self).__init__() print "A init" def meth(self): print "A.meth" class B(object): __metaclass__ = MyMeta def __init__(self): super(B, self).__init__() print "B init" def meth(self): print "B.meth" class C(A, B): __metaclass__ = MyMeta def __init__(self): super(C, self).__init__() print "C init" >>> c_obj = C() meta: creating A (,) meta: creating B (,) meta: creating C (A, B) B init A init C init >>> c_obj.meth() A.meth >>> C.meta_meth() MyMeta.meta_meth >>> c_obj.meta_meth() Traceback (most recent call last): File "mro.py", line 38, in  c_obj.meta_meth() AttributeError: 'C' object has no attribute 'meta_meth' 

Aquí está la respuesta más pragmática.

Rara vez importa

  1. ” Qué es una metaclase en Python “. En conclusión, el type es la metaclase de todas las clases. Usted no tiene casi ningún uso práctico para esto.

     class X(object): pass type(X) == type 
  2. ” ¿Cuáles son sus casos de uso (concretos) para metaclases en Python? “. Línea de fondo. Ninguna.

  3. ” El Super de Python es ingenioso, pero no puedes usarlo “. Nota interesante, pero poco valor práctico. Nunca tendrás la necesidad de resolver redes de herencia múltiple complejas. Es fácil evitar que este problema surja mediante el uso de un diseño de Estrategia explícito en lugar de la herencia múltiple.

Aquí está mi experiencia en los últimos 7 años de progtwigción en Python.

  1. Una clase tiene 1 o más superclases que forman una cadena simple de mi clase para object .

  2. El concepto de “clase” está definido por una metaclase llamada type . Tal vez quiera extender el concepto de “clase”, pero hasta ahora, nunca se ha presentado en la práctica. Ni una sola vez. type siempre hace lo correcto.

  3. Usar super funciona muy bien en la práctica. Permite que una subclase difiera a su superclase. Sucede que aparece en estos ejemplos de metaclase porque están extendiendo el tipo de metaclase incorporado.

    Sin embargo, en todas las situaciones de subclases, utilizará super para extender una superclase.

Metaclases

El tema de la metaclase es este:

  • Cada objeto tiene una referencia a su definición de tipo, o “clase”.

  • Una class es, en sí misma, también un objeto.

  • Por lo tanto, un objeto de class de tipo tiene una referencia a su tipo o “clase”. La “clase” de una “clase” es una metaclase.

Como una “clase” no es un objeto en tiempo de ejecución de C ++, esto no sucede en C ++. Sucede en Java, Smalltalk y Python.

Una metaclase define el comportamiento de un objeto de clase.

  • El 90% de su interacción con una clase es pedirle a la clase que cree un nuevo objeto.

  • El 10% del tiempo, utilizará métodos de clase o variables de clase (“estática” en C ++ o lenguaje de Java).

He encontrado algunos casos de uso para los métodos de nivel de clase. Casi no tengo casos de uso para las variables de clase. Nunca he tenido una situación para cambiar la forma en que funciona la construcción de objetos.