Accessing Object Memory Address

234,481

Solution 1

The Python manual has this to say about id():

Return the "identity'' of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value. (Implementation note: this is the address of the object.)

So in CPython, this will be the address of the object. No such guarantee for any other Python interpreter, though.

Note that if you're writing a C extension, you have full access to the internals of the Python interpreter, including access to the addresses of objects directly.

Solution 2

You could reimplement the default repr this way:

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

Solution 3

Just use

id(object)

Solution 4

There are a few issues here that aren't covered by any of the other answers.

First, id only returns:

the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.


In CPython, this happens to be the pointer to the PyObject that represents the object in the interpreter, which is the same thing that object.__repr__ displays. But this is just an implementation detail of CPython, not something that's true of Python in general. Jython doesn't deal in pointers, it deals in Java references (which the JVM of course probably represents as pointers, but you can't see those—and wouldn't want to, because the GC is allowed to move them around). PyPy lets different types have different kinds of id, but the most general is just an index into a table of objects you've called id on, which is obviously not going to be a pointer. I'm not sure about IronPython, but I'd suspect it's more like Jython than like CPython in this regard. So, in most Python implementations, there's no way to get whatever showed up in that repr, and no use if you did.


But what if you only care about CPython? That's a pretty common case, after all.

Well, first, you may notice that id is an integer;* if you want that 0x2aba1c0cf890 string instead of the number 46978822895760, you're going to have to format it yourself. Under the covers, I believe object.__repr__ is ultimately using printf's %p format, which you don't have from Python… but you can always do this:

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

* In 3.x, it's an int. In 2.x, it's an int if that's big enough to hold a pointer—which is may not be because of signed number issues on some platforms—and a long otherwise.

Is there anything you can do with these pointers besides print them out? Sure (again, assuming you only care about CPython).

All of the C API functions take a pointer to a PyObject or a related type. For those related types, you can just call PyFoo_Check to make sure it really is a Foo object, then cast with (PyFoo *)p. So, if you're writing a C extension, the id is exactly what you need.

What if you're writing pure Python code? You can call the exact same functions with pythonapi from ctypes.


Finally, a few of the other answers have brought up ctypes.addressof. That isn't relevant here. This only works for ctypes objects like c_int32 (and maybe a few memory-buffer-like objects, like those provided by numpy). And, even there, it isn't giving you the address of the c_int32 value, it's giving you the address of the C-level int32 that the c_int32 wraps up.

That being said, more often than not, if you really think you need the address of something, you didn't want a native Python object in the first place, you wanted a ctypes object.

Solution 5

Just in response to Torsten, I wasn't able to call addressof() on a regular python object. Furthermore, id(a) != addressof(a). This is in CPython, don't know about anything else.

>>> 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
Share:
234,481

Related videos on Youtube

thr
Author by

thr

Updated on December 29, 2021

Comments

  • thr
    thr over 2 years

    When you call the object.__repr__() method in Python you get something like this back:

    <__main__.Test object at 0x2aba1c0cf890> 
    

    Is there any way to get a hold of the memory address if you overload __repr__(), other then calling super(Class, obj).__repr__() and regexing it out?

  • Admin
    Admin almost 13 years
    >>> import ctypes >>> a = (1,2,3) >>> ctypes.addressof(a) Traceback (most recent call last): File "<input>", line 1, in <module> TypeError: invalid type >>> id(a) 4493268872 >>>
  • Brandon Rhodes
    Brandon Rhodes about 10 years
    I concur with Barry: the above code results in TypeError: invalid type when I try it with Python 3.4.
  • Brandon Rhodes
    Brandon Rhodes about 10 years
    Unless you use the built-in ctypes toolkit in the Standard Library. In which case you can do all sorts of things with the address :)
  • DilithiumMatrix
    DilithiumMatrix over 9 years
    This is not a universal answer to the question; it only applies to CPython.
  • Artyer
    Artyer over 7 years
    I know this is old, but you can just do return object.__repr__(self) or even just do object.__repr__(obj) whenever you need this instead of making a new class
  • JLT
    JLT over 7 years
    which gives a number. ... What's next? Can i access the object with that number?
  • Rufus
    Rufus over 7 years
    Note to self: The guarantee does not apply to multiprocessing
  • Rafe
    Rafe over 7 years
    @Artyer: What does this comment have to do with the original question? The answer posted here is recreating the address as requested by the original question. Wouldn't you have to string mangle if you did it the way you suggest?
  • Rafe
    Rafe over 7 years
    This seems like the best answer to me. Just try making an object(), print it, then print hex(id(object)) and the results match
  • Artyer
    Artyer over 7 years
    @Rafe Your answer is a long winded way of doing __repr__ = object.__repr__, and isn't nearly as fool proof, as there are a variety of situations where this doesn't work, e.g. an overrided __getattribute__ or a non-CPython implementation where the id isn't the memory location. It also doesn't z-fill, so you would have to work out if the system is 64bit and add the zeroes as necessary.
  • J. Does
    J. Does over 7 years
    Some ways to use it (to compare the value it contains): forum.freecodecamp.com/t/python-id-object/19207
  • Billal Begueradj
    Billal Begueradj about 7 years
    You can check this id() @JLT
  • Rafe
    Rafe almost 7 years
    @Artyer: My example shows how to construct a repr. We often add custom information (and I would say this is good coding practice as it aids in debugging). We use this style heavily and I have never run in to your edge cases. Thanks for sharing them!
  • Minh Tran
    Minh Tran about 6 years
    What does an object's lifetime (and what does it mean for lifetime to overlap/not overlap) refer to in this context?
  • Joshua Clayton
    Joshua Clayton almost 6 years
    @MinhTran because the id is the memory address of the object, it is guaranteed unique within the process, and while the object exists. Some time after the object is garbage collected the memory may be reused. A non overlapping lifetime would mean the original object no longer exists when the new object is created. So this limitation means you can't safely use id() to create a hash of an object to store off, free it, and later reinstate it.
  • Enerccio
    Enerccio almost 6 years
    well this is the only way to store mutable objects in maps/sets when identity is important...
  • abarnert
    abarnert almost 6 years
    @Enerccio The other uses of id—including using them to hold mutable values in a seen set or a cache dict—don’t depend on any way on the id being a pointer, or related in any way to the repr. Which is exactly why such code works in all Python implementations, instead of only working in CPython.
  • Enerccio
    Enerccio almost 6 years
    yeah, I used id for it, but I mean still even in java you can get address of object, seems strange there is no way in (C)Python since that one has actually stable gc that won't move objects thus address stays the same
  • abarnert
    abarnert almost 6 years
    @Enerccio But you don't want to use the address of an object for a cacheable value—you want to use the id fo an object, whether it's an address or not. For example, in PyPy, id is still just as useful as a key in CPython, even though it's usually just an index into some hidden table in the implementation, but a pointer would be useless, because (like Java) the object can be moved in memory.
  • abarnert
    abarnert almost 6 years
    @Enerccio Anyway, there is a way to get a pointer in CPython. As explained in the answer, CPython explicitly documents, as an implementation-specific detail, that the id of an object is the pointer to the object's location in memory. So, if you have any use for the pointer value (which you almost never do, as also explained in the answer) in CPython-specific code, there is a way to get it that's documented and guaranteed to work.
  • juanpa.arrivillaga
    juanpa.arrivillaga about 3 years
    @DilithiumMatrix well, it is not a universal that the number you are seeing in an object repr is the memory address.