Necesito entender el flujo de __init__, __new__ y __call__

class Singleton(type): def __init__(self, *args, **kwargs): print 'calling __init__ of Singleton class', self print 'args: ', args print 'kwargs: ', kwargs super(Singleton, self).__init__(*args, **kwargs) self.__instance = None def __call__(self, *args, **kwargs): print 'running __call__ of Singleton', self print 'args: ', args print 'kwargs: ', kwargs, '\n\n' if self.__instance is None: self.__instance = super(Singleton, self).__call__(*args, **kwargs) return self.__instance class A(object): __metaclass__ = Singleton def __init__(self,a): print 'in __init__ of A: ', self self.a = a print 'self.a: ', self.a a=A(10) b=A(20) 

Copié este código de la respuesta de Ben a la pregunta del uso de Python de __new__ y __init__? Y lo modifiqué un poco. Pero, no soy consciente de la stream. Aunque entiendo desde un nivel superior lo que este código pretende hacer. Pero, internamente, cómo funciona, no estoy muy seguro.

Obtengo el siguiente resultado cuando ejecuto este código:

 calling __init__ of Singleton class  args: ('A', (,), {'__module__': '__main__', '__metaclass__': , '__init__': }) kwargs: {} running __call__ of Singleton  args: (10,) kwargs: {} in __init__ of A:  self.a: 10 running __call__ of Singleton  args: (20,) kwargs: {} 

No puedo entender cómo los kwargs y kwargs para __init__ y __call__ vuelven diferentes. Al usar metaclases, este enlace ( ¿Qué es una metaclase en Python? ) Ha explicado cómo usar __new__ y una función como metaclase. Pero, no entiendo cómo se usa __call__ .

¿Alguien puede explicar el flujo? Con esto, quiero decir, la prioridad con la que se __new__ , __call__ , __init__ y quién los llama?

Su código no incluye ningún __new__ , por lo que poco se puede decir al respecto.

Pero creas una metaclase que se crea una instancia en el momento en que se crea la clase A En otras palabras, la clase A es un objeto en sí mismo y, como tal, una instancia de su metaclase Singleton .

Así que vamos a ver qué pasa:

A finalizado el entorno de A (existen sus métodos, también existe su dictado, …), la clase se crea como una instancia de la metaclase. Esencialmente, la llamada es

 A = Singleton('A', (object,), ) 

donde es el dict que contiene el espacio de nombres de la clase (aquí: __module__ , __metaclass__ y __init__ ).

En esta llamada a Singleton , llamar a super(Singleton, self).__call__(*args, **kwargs) da como resultado que se llame al método __new__ que devuelve una nueva instancia, en la que se llama posteriormente a .__init__ .

Por eso sucede esto:

 calling __init__ of Singleton class  args: ('A', (,), {'__module__': '__main__', '__metaclass__': , '__init__': }) kwargs: {} 

A se construye A, lo usas por instanciación:

 a = A(10) 

Esto llama a. A es una instancia de Singleton , por Singleton.__call__ se invoca Singleton.__call__ , con el efecto que se ve:

 running __call__ of Singleton  args: (10,) kwargs: {} 

Singleton.__call__ calls type.__call__ , esto llama A.__new__ y A.__init__ :

 in __init__ of A: <__main__.A object at 0x01FA7A10> self.a: 10 

Entonces tu haces

 b = A(20) 

que llama Singleton.__call__ :

 running __call__ of Singleton  args: (20,) kwargs: {} 

Aquí se suprime la super llamada y se devuelve el objeto antiguo.