programacion - poo python 3
¿Cómo obtener el nombre de la clase que llama dentro de una función de otra clase en python? (5)
Bueno, después de un poco de excavación en el indicador, esto es lo que obtengo:
stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__
the_method = stack[1][0].f_code.co_name
print("I was called by {}.{}()".format(str(calling_class), calling_code_name))
# => I was called by A.a()
Cuando se invoca:
➤ python test.py
A.a()
B.b()
I was called by __main__.A.a()
dado el archivo test.py
:
import inspect
class A:
def a(self):
print("A.a()")
B().b()
class B:
def b(self):
print("B.b()")
stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__
the_method = stack[1][0].f_code.co_name
print(" I was called by {}.{}()".format(str(the_class), the_method))
A().a()
No estoy seguro de cómo se comportará cuando se le llame desde algo que no sea un objeto.
Mi objetivo es estimular un diagrama de secuencia de una aplicación para esto. Necesito la información sobre los nombres de las clases de la persona que llama y la persona que llama en el tiempo de ejecución. ¿Puedo recuperar con éxito la función de la persona que llama pero no puedo obtener un nombre de clase de la persona que llama?
#Scenario caller.py:
import inspect
class A:
def Apple(self):
print "Hello"
b=B()
b.Bad()
class B:
def Bad(self):
print"dude"
print inspect.stack()
a=A()
a.Apple()
Cuando imprimí la pila no había información acerca de la clase que llamaba. Entonces, ¿es posible recuperar la clase que llama durante el tiempo de ejecución?
En lugar de indexar el valor de retorno de inspect.stack (), se podría usar el método inspect.currentframe (), que evita la indexación.
prev_frame = inspect.currentframe().f_back
the_class = prev_frame.f_locals["self"].__class__
the_method = prev_frame.f_code.co_name
Para almacenar el nombre de instancia de clase de la pila a la variable de clase:
import inspect
class myClass():
caller = ""
def __init__(self):
s = str(inspect.stack()[1][4]).split()[0][2:]
self.caller = s
def getInstanceName(self):
return self.caller
Esta
myClassInstance1 = myClass()
print(myClassInstance1.getInstanceName())
imprimirá:
myClassInstance1
Quizás esto está rompiendo algún protocolo de programación de Python, pero si Bad siempre va a verificar la clase de la persona que llama, ¿por qué no pasarle la __class__
la persona que llama como parte de la llamada?
class A:
def Apple(self):
print "Hello"
b=B()
b.Bad(self.__class__)
class B:
def Bad(self, cls):
print "dude"
print "Calling class:", cls
a=A()
a.Apple()
Resultado:
Hello
dude
Calling class: __main__.A
Si esta es una forma incorrecta, y usar la función de inspect
verdaderamente es la forma preferida de obtener la clase de la persona que llama, explique por qué. Todavía estoy aprendiendo sobre conceptos más profundos de Python.
Usando la respuesta de Python: ¿Cómo recuperar información de clase de un objeto ''marco''?
Me sale algo como esto ...
import inspect
def get_class_from_frame(fr):
args, _, _, value_dict = inspect.getargvalues(fr)
# we check the first parameter for the frame function is
# named ''self''
if len(args) and args[0] == ''self'':
# in that case, ''self'' will be referenced in value_dict
instance = value_dict.get(''self'', None)
if instance:
# return its class
return getattr(instance, ''__class__'', None)
# return None otherwise
return None
class A(object):
def Apple(self):
print "Hello"
b=B()
b.Bad()
class B(object):
def Bad(self):
print"dude"
frame = inspect.stack()[1][0]
print get_class_from_frame(frame)
a=A()
a.Apple()
Lo que me da la siguiente salida:
Hello
dude
<class ''__main__.A''>
claramente esto devuelve una referencia a la clase en sí. Si desea el nombre de la clase, puede obtenerlo del atributo __name__
.
Desafortunadamente, esto no funcionará para la clase o métodos estáticos ...