Objeto llamador introspectivo

¿Cómo hago una introspección de la instancia de A desde b.func() (es decir, la propia instancia de A) ?:

 class A(): def go(self): b=B() b.func() class B(): def func(self): # Introspect to find the calling A instance here 

En general, no queremos que esa func tenga acceso de nuevo a la instancia de llamada de A porque esto rompe la encapsulación . Dentro de b.func debe tener acceso a cualquier argumento y kwargs aprobados, al estado / a los atributos de la instancia b (a través de self aquí), y a los globales que estén por ahí.

Si desea saber acerca de un objeto que llama, las formas válidas son:

  1. Pase el objeto llamante como un argumento a la función
  2. Agregue explícitamente un identificador a la persona que llama en la instancia de b algún momento antes de usar func , y luego acceda a ese identificador a través de self .

Sin embargo , con ese descargo de responsabilidad fuera del camino, todavía vale la pena saber que las capacidades de introspección de python son lo suficientemente poderosas como para acceder al módulo de llamadas en algunos casos. En la implementación de CPython, aquí se explica cómo puede acceder a la instancia A llamada sin cambiar sus interfaces:

 class A(): def go(self): b=B() b.func() class B(): def func(self): import inspect print inspect.currentframe().f_back.f_locals['self'] if __name__ == '__main__': a = A() a.go() 

Salida:

 <__main__.A instance at 0x15bd9e0> 

Este podría ser un truco útil que se debe conocer para depurar el código algunas veces. Pero no sería una decisión de diseño sensata acceder a los marcos de la stack como esta en el caso de que B.func realmente necesitara usar A por cualquier motivo.

Se lo pasas a b.func() como argumento.

Haz esto refactorizando tu código para que funcione como

 class A(): def go(self): b = B(self) b.func() class B(): def __init__(self, a): self.a = a def func(self): # Use self.a 

o

 class A(): def go(self): b = B() b.func(self) class B(): def func(self, a): # a 

Estoy de acuerdo con Benjamin: pásalo a b.func () como argumento y no lo intentes.

Si tu vida realmente depende de ello, entonces creo que puedes deducir la respuesta de esta respuesta .