2010-04-09 12 views
1

Avant de demander cela, notez: Je le souhaite à des fins de débogage. Je sais que cela va être une mauvaise magie noire, mais je veux l'utiliser juste pendant le débogage afin que je puisse identifier mes objets plus facilement.Obtention du nom d'attribut que l'objet créé sera donné

C'est comme ça. J'ai un objet de la classe A qui crée quelques B cas comme attributs:

class A(object): 
    def __init__(self) 
     self.vanilla_b = B() 
     self.chocolate_b = B() 

class B(object): 
    def __init__(self): 
     # ... 

Ce que je veux est que dans B.__init__, il figurera le "vanilla_b" ou quel que soit le nom d'attribut, il a été donné, puis mis que l'attribut .name à ce B spécifique.

Ensuite, lors du débogage, lorsque je vois un objet B qui flotte, je peux savoir de quel objet il s'agit.

Y at-il un moyen de le faire?

Répondre

2

Vous pouvez utiliser sys._getframe pour obtenir le numéro de ligne où B() est appelé, puis vous pouvez utiliser inspect.getsourcelines pour obtenir la ligne de code réelle. De là, vous pouvez analyser la ligne de code pour obtenir la chose à laquelle B() est attribué:

import sys 
import inspect 

class A(object): 
    def __init__(self): 
     self.vanilla_b = B() 
     self.chocolate_b = B() 

class B(object): 
    def __init__(self): 
     line_num = sys._getframe().f_back.f_lineno 
     lines = inspect.getsourcelines(sys.modules[__name__])[0] 
     line = lines[line_num - 1] 
     attr = line.split("=")[0].split(".")[1].strip() 
     print "B() is being assigned to", attr 

A() 

Si vous mettez le code ci-dessus dans un script python et l'exécuter, il imprimera

B() is being assigned to vanilla_b 
B() is being assigned to chocolate_b 

Cependant, cela ne fonctionnera pas à l'invite de commande Python, puisque __main__ est un module intégré, et donc le module d'inspection ne peut pas récupérer ses lignes source. Donc, vous pourriez vouloir envelopper dans un bloc try/catch ou quelque chose juste au cas où votre code serait jamais appelé à partir de n'importe quel module intégré. Pour l'anecdote, c'est probablement une mauvaise idée, mais vous dites que vous êtes conscient que ce n'est pas une bonne pratique et que vous ne le faites que pour le débogage, donc j'espère que vous pourrez utiliser ce genre de tricherie à bon escient.

+0

Ah, attacher le nom de fichier au code serait trop ennuyeux. –

+0

@ cool-RR: J'ai modifié la réponse pour utiliser le module d'inspection afin de ne pas avoir à taper le nom du fichier. –

0

Ceci est probablement pas la réponse que vous cherchez, mais peut-être que vous pourriez faire quelque chose le long de cette:

class A(object): 
    def __init__(self): 
     attrs = ('vanilla_b', 'chocolate_b') 

     for attr in attrs: 
      instance = B() 
      setattr(self, attr, instance) 
      instance.name = attr 

Essayez d'envelopper ce comportement à certains superclasse et vous pourriez être bon d'aller.

+0

Un peu problématique, je veux avoir différents paramètres dans la création de chaque 'B'. S'il n'y a pas assez de magie, je pourrais prendre cette méthode. –

+0

Ok. Pour contourner ce problème, vous pouvez instancier des attributs en tant que dict (clé = nom, valeur = objet). –

0

Si vous avez le contrôle sur le code, alors il est préférable de le faire simplement, puis compter sur de la magie noire, par ex. ne

class A(object): 
    def __init__(self) 
     self.vanilla_b = B(name="vanilla_b") 
     self.chocolate_b = B(name="chocolate_b") 

sinon vous pouvez utiliser inspecter module pour passer par la population locale et l'auto dans le cadre prev et faire quelques vodou.

+0

Je suis au courant de cette méthode, merci. Ma question entière est, "comment je fais le vaudou?" –

-1

Pas magique, mais:

class A(object): 
    def __init__(self) 
     self.vanilla_b = B(self) 
     self.chocolate_b = B(self) 

et:

class B(object): 
    def __init__(self, a): 
     for i in dir(a): 
      if getattr(a, i) == self: 
       pass # store it somewhere now 

EDIT: Désolé, cela ne fonctionnera pas. B. init est exécuté avant que les références dans A soient définies.

+0

Pas bon, l'objet 'B' ne devrait pas avoir une référence à' A'. –