Можно ли получить «значение адреса» в python? - PullRequest
0 голосов
/ 20 октября 2019

В дальнейшем я вижу, что при добавлении целого числа в python оно добавляет целое число, присваивает это результирующее значение новому адресу памяти и затем устанавливает переменную, указывающую на этот адрес памяти:

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

Есть ли способ узнать, какое значение у (старого) адреса памяти 4304852448 (0x10096d5e0)? Например: value_of(0x10096d5e0)

Ответы [ 2 ]

4 голосов
/ 20 октября 2019

добавляет целое число, присваивает результирующее значение новому адресу памяти

Нет; объект, который представляет результирующее значение имеет другой адрес памяти. Обычно этот объект создается на лету, но специально для целых чисел (которые являются неизменяемыми, и для некоторых других типов, применяющих аналогичную оптимизацию), объект может уже существовать и использоваться повторно.

Есть ли способчтобы увидеть, какое значение у (старого) адреса памяти 4304852448 (0x10096d5e0) есть?

Этот вопрос не совсем корректен. Во-первых, «адреса памяти» в этом контексте виртуализируются, возможно, более одного раза. Во-вторых, в модели Python адреса не имеют «значений». Они потенциально являются местоположением объектов, которые, в свою очередь, представляют значения.

При этом в месте расположения предыдущего id(a) старый объект все равно будет присутствовать, если и только если он не был мусором. собраны. Для этого достаточно, чтобы к объекту содержалась какая-то другая ссылка. (Время сборки мусора определяется реализацией, но эталонная реализация CPython реализует сборку мусора путем подсчета ссылок.)

Как правило, вы не имеете права напрямую исследовать основную память (за исключением, возможно, некоторого вида). процесса шпион, который имеет соответствующие разрешения), потому что Python просто не такой низкий уровень языка. (Как и в ответе @ xprilion, реализация CPython предоставляет интерфейс памяти более низкого уровня через ctypes; однако код там эффективно выполняет небезопасное приведение.)

Если вы это сделали (и предполагаете, что CPython),вы бы не увидели двоичное представление целого числа 100 в ячейке памяти, указанной при первом вызове id(a) - вместо этого вы бы увидели первое слово структуры PyObject, использованной для реализации объектовв коде C, который (если я правильно читаю , это ) будет указателем на следующий объект динамической кучи (все связаны в двусвязном списке).

Как только этосборщик мусора, содержимое этой памяти снова undefined. Они зависят от реализации, и даже специально для реализации C, они зависят от того, что стандартная библиотека free () делает с памятью. (Обычно это не трогают, потому что нет нужды обнулять его, и для этого требуется время. Отладочная сборка может записать специальные значения в эту память, потому что это помогает обнаружить повреждение памяти.)

3 голосов
/ 20 октября 2019

Вы пытаетесь разыменовать адрес памяти, так же, как указатели, используемые в C / C ++. Следующий код может помочь вам -

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

В приведенном выше примере показано, что значение, сохраненное в предыдущем адресе a, остается прежним.

Надеюсь, что это отвечает на вопрос. Прочитайте ответ @ Карла для получения дополнительной информации о том, что происходит в фоновом режиме - https://stackoverflow.com/a/58468810/2650341

...