117 votes

Python : Récupérer un objet par son identifiant

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é ?

169voto

HYRY Points 26340

Cela peut être fait facilement en ctypes :

import ctypes
a = "hello world"
print ctypes.cast(id(a), ctypes.py_object).value

sortie :

hello world

38voto

Manuel Ceron Points 3568

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")

36voto

chaos Points 69029

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.

34voto

Ken Points 3228

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.

9voto

Unknown Points 22789

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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X