Question

Lorsque vous appelez la méthode object .__ de la méthode repr __ () en Python, vous obtenez quelque chose comme ceci:

<__main__.Test object at 0x2aba1c0cf890> 

Existe-t-il un moyen de récupérer l'adresse de la mémoire si vous surchargez __ repr __ () , autrement qu'en appelant super (Classe, obj) .__ repr __ () et regexing out?

Était-ce utile?

La solution

Le Le manuel Python a ceci à dire à propos de id () :

  

Renvoie la "identité" d'un objet.   Ceci est un entier (ou un entier long)   qui est garanti d'être unique et   constante pour cet objet au cours de sa   durée de vie. Deux objets avec   des durées de vie non chevauchantes peuvent avoir la   même id () valeur. (Note d'implémentation:   c'est l'adresse de l'objet.)

Donc, dans CPython, ce sera l'adresse de l'objet. Aucune garantie de ce type n’est offerte pour les autres interpréteurs Python.

Notez que si vous écrivez une extension C, vous avez un accès complet aux éléments internes de l'interpréteur Python, y compris l'accès direct aux adresses des objets.

Autres conseils

Vous pouvez réimplémenter le repr par défaut de cette façon:

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )

Il suffit d'utiliser

id(object)

Il y a quelques problèmes ici qui ne sont couverts par aucune des autres réponses.

Tout d'abord, id ne renvoie que :

  

"l'identité" d'un objet. C'est un entier (ou un entier long) qui est garanti d'être unique et constant pour cet objet pendant sa durée de vie. Deux objets dont la durée de vie ne se chevauchent pas peuvent avoir la même valeur id () .

Dans CPython, il s’agit du pointeur sur le PyObject qui représente l'objet dans l'interpréteur, ce qui est la même chose que objet .__ repr __ . Mais il ne s'agit que d'un détail d'implémentation de CPython, et non de Python en général. Jython ne traite pas les pointeurs, il traite les références Java (que la machine virtuelle Java représente probablement comme des pointeurs, mais vous ne pouvez pas les voir - et vous ne voudriez pas, car le GC est autorisé à les déplacer). PyPy permet à différents types d’avoir différents types id , mais le plus général est simplement un index dans une table d’objets que vous avez nommée id , ce qui ne va évidemment pas se produire. être un pointeur. Je ne suis pas sûr d’IronPython, mais j’imagine que c’est plus comme Jython que CPython à cet égard. Donc, dans la plupart des implémentations Python, il n’ya aucun moyen d’obtenir ce qui apparaît dans ce repr , et aucune utilité si vous l’avez fait.

Mais que se passe-t-il si vous vous souciez uniquement de CPython? C'est un cas assez courant, après tout.

Tout d’abord, vous remarquerez peut-être que id est un entier; * si vous souhaitez que cette chaîne 0x2aba1c0cf890 soit remplacée par le nombre 46978822895760 , vous allez devoir le formater vous-même. Sous les couvertures, je crois que objet .__ repr __ utilise finalement le format printf de % p , que vous n'avez pas dans Python… mais vous pouvez toujours faire ceci:

format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')

* Dans 3.x, c'est un int . Dans 2.x, il s'agit d'un int s'il est assez gros pour contenir un pointeur (ce qui n'est peut-être pas dû à des problèmes de numéros signés sur certaines plateformes) et d'un long sinon.

Pouvez-vous faire quelque chose avec ces pointeurs en plus de les imprimer? Bien sûr (encore une fois, en supposant que vous vous souciez uniquement de CPython).

Toutes les fonctions de l'API C prennent un pointeur sur un < code> PyObject ou un type associé. Pour ces types liés, vous pouvez simplement appeler PyFoo_Check pour vous assurer qu'il s'agit bien d'un objet Foo , puis transtyper avec (PyFoo *) p . Donc, si vous écrivez une extension C, le id est exactement ce dont vous avez besoin.

Et si vous écrivez du code pur Python? Vous pouvez appeler exactement les mêmes fonctions avec pythonapi à partir de ctypes .

Enfin, quelques-unes des autres réponses ont apporté ctypes.addressof . Ce n'est pas pertinent ici. Cela ne fonctionne que pour les objets ctypes tels que c_int32 (et peut-être quelques objets de type mémoire tampon, comme ceux fournis par numpy ). Et même là, il ne vous donne pas l’adresse de la valeur c_int32 , mais vous donne l’adresse du int32 de niveau C que le c_int32 se termine.

Cela étant dit, le plus souvent, si vous pensez vraiment avoir besoin de l'adresse de quelque chose, vous ne voulez pas d'abord d'objet Python natif, vous voulez un objet ctypes .

Juste en réponse à Torsten, je n'ai pas pu appeler addressof () sur un objet Python normal. De plus, id (a)! = Adresse de (a) . Ceci est en CPython, je ne sais rien d’autre.

>>> from ctypes import c_int, addressof
>>> a = 69
>>> addressof(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: invalid type
>>> b = c_int(69)
>>> addressof(b)
4300673472
>>> id(b)
4300673392

Avec les ctypes , vous pouvez obtenir le même résultat avec

>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L

Documentation:

  

adresse de (instance C) - > entier
  Renvoie l'adresse du tampon interne de l'instance C

Notez que dans CPython, id actuellement (a) == ctypes.addressof (a) , mais ctypes.addressof doit renvoyer la véritable adresse pour chaque implémentation Python, si

  • les types sont supportés
  • les pointeurs de mémoire sont une notion valide.

Modifier : ajout d'informations sur l'indépendance de l'interpréteur des types de caractères

.

Vous pouvez obtenir quelque chose qui convienne à cette fin avec:

id(self)

S'il est vrai que id (objet) obtient l'adresse de l'objet dans l'implémentation CPython par défaut, cela est généralement inutile ... vous ne pouvez pas faire quoi que ce soit avec adresse à partir de code Python pur.

Le seul moment où vous pourrez réellement utiliser l'adresse provient d'une bibliothèque d'extension C ... auquel cas il est trivial d'obtenir l'adresse de l'objet car les objets Python sont toujours transmis en tant que pointeurs C.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top