Disons que j'ai l'identifiant d'un objet Python, que j'ai récupéré par la méthode suivante id(thing)
. Comment puis-je trouver thing
encore par le numéro d'identification qu'on m'a donné ?
Réponses
Trop de publicités?Vous pouvez utiliser le gc pour obtenir tous les objets actuellement suivis par le ramasseur de déchets Python.
import gc
def objects_by_id(id_):
for obj in gc.get_objects():
if id(obj) == id_:
return obj
raise Exception("No found")
Réponse courte, vous ne pouvez pas.
En résumé, vous pouvez gérer une dictée pour faire correspondre les ID aux objets, ou rechercher l'ID en effectuant une recherche exhaustive dans la base de données gc.get_objects()
mais cela créera l'un des deux problèmes suivants : soit la référence du dict maintiendra l'objet en vie et empêchera la GC, soit (s'il s'agit d'un dict de valeur faible ou si vous utilisez gc.get_objects()
) l'ID peut être désalloué et réutilisé pour un objet complètement différent.
En gros, si vous essayez de faire ça, vous devez probablement faire quelque chose de différent.
Vous devrez probablement envisager de l'implémenter d'une autre manière. Connaissez-vous le module weakref ?
(édité) Le Python module weakref vous permet de conserver les références, les références de dictionnaire et les proxies d'objets sans que ces références soient comptabilisées dans le compteur de références. Ils sont comme des liens symboliques.
Je mentionne juste ce module par souci d'exhaustivité. Ce code par Bill Bumgarner comprend une extension C pour faire ce que vous voulez sans passer en boucle par tous les objets existants.
Le code de cette fonction est assez simple. Chaque objet Python est représenté en C par un pointeur sur le fichier a PyObject
struct . Parce que id(x)
est juste l'adresse mémoire de cette structure, nous pouvons récupérer l'objet Python en traitant simplement le fichier x
comme un pointeur vers un PyObject
puis en appelant Py_INCREF
pour dire au ramasseur de déchets que nous créons une nouvelle référence à l'objet.
static PyObject *
di_di(PyObject *self, PyObject *args)
{
PyObject *obj;
if (!PyArg_ParseTuple(args, "l:di", &obj))
return NULL;
Py_INCREF(obj);
return obj;
}
Si l'objet original n'existe plus, le résultat est indéfini. Il peut se planter, mais il peut aussi renvoyer une référence à un nouvel objet qui a pris la place de l'ancien en mémoire.