Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

nom de l'objet depuis la classe

6 réponses
Avatar
Cémoi
Bonsoir,


j'ai défini une classe dont l'une de ses méthodes aimerait retourner en
runtime le nom de l'instance qui l'utilise.
J'ai trouvé plein d'infos sur l'introspection depuis une instance, mais
je ne trouve rien pour faire l'opération en sens inverse.

Existe t'il une solution pour faire cette opération ?


Merci pour votre aide et vos idées,


Laurent

6 réponses

Avatar
Bruno Desthuilliers
Bonsoir,


j'ai défini une classe dont l'une de ses méthodes aimerait retourner en
runtime le nom de l'instance qui l'utilise.
J'ai trouvé plein d'infos sur l'introspection depuis une instance, mais
je ne trouve rien pour faire l'opération en sens inverse.

Existe t'il une solution pour faire cette opération ?


Réponse courte : non.

Réponse longue: "le nom de l'instance qui l'utilise" ne veut rien dire.
Les variables python sont des paires nom=>référenceSurUneInstance dans
un espace de nommage. Un même objet peut être référencé par plusieurs
nom, dans le même espace de nommage ou dans plusieurs espaces de
nommages différents, ie:

# toto.py

toto = list("toto")
tata = toto

class Rominet(object):
titi = tata
def __init__(self, target):
self.target = target

r = Rominet(toto)

def test(titi):
tutu = titi
print titi is toto
print titi is tata
print titi is tutu
print titi is r.target
print titi is Rominet.titi

if __name__ == '__main__':
test(tata)


Quel est "le" nom de la liste créée par la première instruction ?

Avatar
Amaury Forgeot d'Arc
Bonsoir,


j'ai défini une classe dont l'une de ses méthodes aimerait retourner
en runtime le nom de l'instance qui l'utilise.
J'ai trouvé plein d'infos sur l'introspection depuis une instance,
mais je ne trouve rien pour faire l'opération en sens inverse.

Existe t'il une solution pour faire cette opération ?


Réponse courte : non.

Réponse longue: "le nom de l'instance qui l'utilise" ne veut rien dire.
Les variables python sont des paires nom=>référenceSurUneInstance dans
un espace de nommage. Un même objet peut être référencé par plusieurs
nom, dans le même espace de nommage ou dans plusieurs espaces de
nommages différents
...


Il y a une autre façon d'interpréter la question initiale:

class A:
pass

class B:
pass

a = A()
b = B()
b.x = a

Ici, "a est utilisé par b". Et ça peut être utile quelquefois.

Il y a bien un moyen, mais il n'est pas très conseillé en "production",
car il utilise à-côté de l'implémentation de python: le garbage
collector. Ceci dit, je l'ai déjà utilisé pour le débogage:

def getReferringInstances(x):
import gc
for d in gc.get_referrers(x):
# On se limite aux dictionnaires, qui ont une chance
# d'être le __dict__ d'un objet.
if not isinstance(d, dict):
continue
for i in gc.get_referrers(d):
if isinstance(i, B):
# d est donc bien le __dict__ d'une instance.
print "le voici", i

Attention: la fonction get_referrers est un poil sensible:
parmi les "référents" de x, on trouve le cadre d'exécution de la
fonction qui contient la variable locale x, etc. D'où le test un peu
restrictif "isinstance(i, B)".

Attention2: ça ne marche qu'avec CPython (l'implémentation principale du
langage python), et sûrement pas avec Jython par exemple, qui utilise le
garbage collector de Java.

--
Amaury


Avatar
Cémoi
Bonsoir,


j'ai défini une classe dont l'une de ses méthodes aimerait retourner
en runtime le nom de l'instance qui l'utilise.
J'ai trouvé plein d'infos sur l'introspection depuis une instance,
mais je ne trouve rien pour faire l'opération en sens inverse.

Existe t'il une solution pour faire cette opération ?


<snip>



Il y a une autre façon d'interpréter la question initiale:

class A:
pass

class B:
pass

a = A()
b = B()
b.x = a

<snip>


Ma problématique est légèrement différente, je donne un exemple simplifié:

class MaClasse:
def maMéthode (self):
try:
faisqqchose
except MonException:
print xxx, "a rencontré l'erreur trucmachin"


mc = MaClasse ()
a.maMéthode ()




mc a rencontré l'erreur trucmachin





Je ne suis pas certain de trouver par quoi remplacer xxx, ce soir j'ai
un peu de mal à rassembler suffisamment de neurones à l'état éveillé,
mais je jetterai un oeil au module gc dès que je peux.
Ceci dit, le rappel de Bruno sur les noms et les espaces de nommage m'a
fait le plus grand bien.

Merci à tous,

Laurent

PS: pour le debug en général, il me semble que le genre de print que je
souhaite réaliser est assez sympathique et plus lisible que des
representations d'objets sous forme de chaine de caracteres encadrée par <>.



Avatar
Bruno Desthuilliers
Bonsoir,


j'ai défini une classe dont l'une de ses méthodes aimerait retourner
en runtime le nom de l'instance qui l'utilise.
J'ai trouvé plein d'infos sur l'introspection depuis une instance,
mais je ne trouve rien pour faire l'opération en sens inverse.

Existe t'il une solution pour faire cette opération ?


<snip>



Il y a une autre façon d'interpréter la question initiale:

class A:
pass

class B:
pass

a = A()
b = B()
b.x = a

<snip>


Ma problématique est légèrement différente, je donne un exemple simplifié:

class MaClasse:
def maMéthode (self):
try:
faisqqchose
except MonException:
print xxx, "a rencontré l'erreur trucmachin"


mc = MaClasse ()
a.maMéthode ()

mc a rencontré l'erreur trucmachin






Je vais encore passer pour un puriste maniaque extrémiste, mais la
sortie standard est destinée aux sorties normales du programme, pas aux
messages d'erreur (il y a stderr pour ça). Et accessoirement, je ne
pense pas que ce genre de gestion d'erreur soit une bonne idée - logger
l'erreur n'est pas idiot en soi, mais outre que ce n'est pas forcément
la meilleure façon de faire, le minimum serait dans ce cas de relancer
l'erreur après l'avoir loggée.

Je ne suis pas certain de trouver par quoi remplacer xxx,


Si tu veux gérer le log depuis l'intérieur de la classe, le mieux est
d'utiliser un identifiant unique connu de la classe - soit un attribut
(ou une combinaison de), soit au pire l'oid mais ce n'est pas très parlant.

Tu peux bien sûr aussi essayer de te rabattre sur l'infâme
sys._getframe, qui te permettra de parcourir l'espace de nommage de la
frame appelante et d'y repérer le nom qu'y porte ton instance (si elle y
est nommée, ce qui n'est pas garanti - ce pourrait aussi bien être un
élément anonyme d'une collection ou un attribut d'un autre objet...).
Bref, beaucoup d'effort et rien de fiable en retour... L'autre solution
étant de déplacer le try/except dans le code appelant !-)

(snip)

PS: pour le debug en général, il me semble que le genre de print que je
souhaite réaliser est assez sympathique et plus lisible que des
representations d'objets sous forme de chaine de caracteres encadrée par
<>.


Si tu es l'auteur de MaClasse, personne ne t'empêche de redéfinir
__repr__ pour avoir quelque chose de plus parlant. En général, je fais
ça au moins pour toutes mes classes 'modèle' (dans l'acceptation MVC).

HTH




Avatar
Cémoi

<snip>

Ma problématique est légèrement différente, je donne un exemple
simplifié:

class MaClasse:
def maMéthode (self):
try:
faisqqchose
except MonException:
print xxx, "a rencontré l'erreur trucmachin"


mc = MaClasse ()
mc.maMéthode ()

mc a rencontré l'erreur trucmachin






Je vais encore passer pour un puriste maniaque extrémiste, mais la
sortie standard est destinée aux sorties normales du programme, pas aux
messages d'erreur (il y a stderr pour ça).


Oui, je n'ai gardé dans l'exemple que le minimum pour montrer que le but
est d'avoir au sein d'une méthode un moyen pour accéder au nom de
l'objet qui risque un jour d'instancier la classe et de faire appel à la
méthode.

Et accessoirement, je ne
pense pas que ce genre de gestion d'erreur soit une bonne idée - logger
l'erreur n'est pas idiot en soi, mais outre que ce n'est pas forcément
la meilleure façon de faire, le minimum serait dans ce cas de relancer
l'erreur après l'avoir loggée.


Oui, même raison que ci-dessus.

Je ne suis pas certain de trouver par quoi remplacer xxx,



<snip>


Si tu es l'auteur de MaClasse, personne ne t'empêche de redéfinir
__repr__ pour avoir quelque chose de plus parlant. En général, je fais


Pourquoi pas, mais dans l'exemple proposé, je ne sais toujours pas
comment récupérer 'mc'.

Merci pour l'aide,

Laurent

ça au moins pour toutes mes classes 'modèle' (dans l'acceptation MVC).

HTH






Avatar
Bruno Desthuilliers

<snip>


Ma problématique est légèrement différente, je donne un exemple
simplifié:

class MaClasse:
def maMéthode (self):
try:
faisqqchose
except MonException:
print xxx, "a rencontré l'erreur trucmachin"


mc = MaClasse ()
mc.maMéthode ()

mc a rencontré l'erreur trucmachin







Je vais encore passer pour un puriste maniaque extrémiste, mais la
sortie standard est destinée aux sorties normales du programme, pas
aux messages d'erreur (il y a stderr pour ça).



Oui, je n'ai gardé dans l'exemple que le minimum pour montrer que le but
est d'avoir au sein d'une méthode un moyen pour accéder au nom de
l'objet qui risque un jour d'instancier la classe et de faire appel à la
méthode.


Ce n'est pas l'objet qui instancie la classe - ni qui appelle la méthode
-, et ce n'est pas l'objet qui a un nom, mais un nom qui est lié à l'objet.


(snip)
Je ne suis pas certain de trouver par quoi remplacer xxx,




<snip>


Si tu es l'auteur de MaClasse, personne ne t'empêche de redéfinir
__repr__ pour avoir quelque chose de plus parlant. En général, je fais


Pourquoi pas, mais dans l'exemple proposé, je ne sais toujours pas
comment récupérer 'mc'.



Comme je le disais, tu peux toujours t'amuser a essayer de récupérer
le(s) nom(s) liés à l'objet dans la frame appellant la méthode, mais ce
n'est pas fiable, et surtout ça n'a pas généralement beaucoup de sens.