Possible to get "value of address" in python?

Question:

In the following, I can see that when adding an integer in python, it adds the integer, assigns that resultant value to a new memory address and then sets the variable to point to that memory address:

>>> a=100
>>> id(a)
4304852448
>>> a+=5
>>> id(a)
4304852608

Is there a way to see what the value is at the (old) memory address 4304852448 (0x10096d5e0) is? For example: value_of(0x10096d5e0)

Asked By: David542

||

Answers:

You are trying to dereference the memory address, much like the pointers used in C/C++. The following code might help you –

import ctypes

a = 100
b = id(a)

print(b, ": ", a)

a+=5
print(id(a), ": ", a)

print(ctypes.cast(b, ctypes.py_object).value)

OUTPUT:

140489243334080 :  100
140489243334240 :  105
100

The above example establishes that the value stored in the previous address of a remains the same.

Hope this answers the question. Read @Karl’s answer for more information about what’s happening in the background – https://stackoverflow.com/a/58468810/2650341

Answered By: xprilion

it adds the integer, assigns that resultant value to a new memory address

No; the object that represents the resulting value has a different memory address. Typically this object is created on the fly, but specifically for integers (which are immutable, and for some other types applying a similar optimization) the object may already exist and be reused.

Is there a way to see what the value is at the (old) memory address 4304852448 (0x10096d5e0) is?

This question is not well posed. First off, "memory addresses" in this context are virtualized, possibly more than once. Second, in the Python model, addresses do not "have values". They are potentially the location of objects, which in turn represent values.

That said: at the location of the previous id(a), the old object will still be present if and only if it has not been garbage-collected. For this, it is sufficient that some other reference is held to the object. (The timing of garbage collection is implementation-defined, but the reference CPython implementation implements garbage collection by reference counting.)

You are not, in general, entitled to examine the underlying memory directly (except perhaps with some kind of process spy that has the appropriate permissions), because Python is just not that low-level of a language. (As in @xprilion’s answer, the CPython implementation provides a lower-level memory interface via ctypes; however, the code there is effectively doing an unsafe cast.)

If you did (and assuming CPython), you would not see a binary representation of the integer 100 in the memory location indicated by calling id(a) the first time – you would see instead the first word of the PyObject struct used to implement objects in the C code, which would usually be the refcount, but could be a pointer to the next live heap object in a reference-tracing Python build (if I’m reading it correctly).

Once it’s garbage-collected, the contents of that memory are again undefined. They depend on the implementation, and even specifically for the C implementation, they depend on what the standard library free() does with the memory. (Normally it will be left untouched, because there is no reason to zero it out and it takes time to do so. A debug build might write special values into that memory, because it helps detect memory corruption.)

Answered By: Karl Knechtel
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.