Mon objectif est de stimuler le diagramme de séquence d'une application pour cela. J'ai besoin des informations sur un appelant et des noms de classe appelés au moment de l'exécution. Je parviens à récupérer la fonction appelant mais je ne parviens pas à obtenir un nom de classe d'appelant?
#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()
Lorsque j'ai imprimé la pile, il n'y avait aucune information sur la classe d'appelant. Est-il donc possible de récupérer la classe de l'appelant pendant l'exécution?
Eh bien, après quelques recherches à l’Invite, voici ce que j’obtiens:
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()
Lorsque invoqué:
➤ python test.py
A.a()
B.b()
I was called by __main__.A.a()
étant donné le fichier 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()
Vous ne savez pas comment il se comportera lorsqu'il est appelé par autre chose qu'un objet.
Utilisation de la réponse de Python: Comment récupérer les informations de classe d’un objet 'frame'?
Je reçois quelque chose comme ça ...
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()
ce qui me donne la sortie suivante:
Hello
dude
<class '__main__.A'>
clairement, cela renvoie une référence à la classe elle-même. Si vous voulez le nom de la classe, vous pouvez l'obtenir à partir de l'attribut __name__
.
Malheureusement, cela ne fonctionnera pas pour les méthodes de classe ou statiques ...
Cela enfreint peut-être certains protocoles de programmation Python, mais si Bad est toujours va vérifier la classe de l'appelant, pourquoi ne pas lui transmettre le __class__
de l'appelant dans le cadre de l'appel?
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()
Résultat:
Hello
dude
Calling class: __main__.A
S'il s'agit d'une mauvaise forme et que vous utilisez inspect
comme méthode privilégiée pour obtenir le cours, veuillez expliquer pourquoi. J'apprends encore sur les concepts plus profonds de Python.
Au lieu d'indexer la valeur de retour de inspect.stack (), on pourrait utiliser la méthode inspect.currentframe (), qui évite l'indexation.
prev_frame = inspect.currentframe().f_back
the_class = prev_frame.f_locals["self"].__class__
the_method = prev_frame.f_code.co_name
Pour stocker le nom d'instance de classe de la pile dans la variable de classe:
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
Ce
myClassInstance1 = myClass()
print(myClassInstance1.getInstanceName())
imprimera:
myClassInstance1