Как Python знает, где найти созданное неизменное значение, когда исходная ссылка теперь указывает на новое значение? - PullRequest
1 голос
/ 09 ноября 2019

Предположим, у меня есть этот код:

myInt = 5
myInt = 7
myInt2 = 5

Целые числа неизменны, поэтому при запуске строки 2 Python перестает указывать на адресную память, где хранится 5, и начинает указывать, где хранится 7. НО 5 значение все еще там, но никто не указывает на него.

  1. Так как же Python знает, куда указывать, когда запускается строка 3?
  2. Пройдет ли он все блоки памяти или адреса, пока не найдет значение 5?
  3. Или он будет разделен в памяти, кеше или таблице, в которой нет ссылок на значенияхранятся?

Спасибо!

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

Или он хранится отдельно, в памяти, в кэше или в таблице, где хранятся нессылочные значения?

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

Ни 5, ни 7 не будут созданы или удалены, поскольку они былиуже интернированы, и они будут оставаться в интерне до выхода из интерпретатора.

Таким образом, присвоение этим значениям просто увеличит или уменьшит их счетчик ссылок, как вы можете проверить с помощью stdlib gc module:

>>> import gc
>>> def counts():
...     print("refcount5:", len(gc.get_referrers(5)))
...     print("refcount7:", len(gc.get_referrers(7)))
... 
>>> counts()
refcount5: 10
refcount7: 7
>>> myInt = 5  # this will increment 5's refcount
>>> counts()
refcount5: 11
refcount7: 7
>>> myInt = 7  # this will decrement 5's refcount and increment 7's
>>> counts()
refcount5: 10
refcount7: 8
>>> myInt2 = 5  # this will increment 5's refcount
>>> counts()
refcount5: 11
refcount7: 8

Вы можете увидеть код, который извлекается из intern здесь :

#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)

...

PyObject *
PyLong_FromLong(long ival)
{
    ...

    if (IS_SMALL_INT(ival)) {
        return get_small_int((sdigit)ival);
    }
    ...
}

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

0 голосов
/ 09 ноября 2019

В структуре кучи Python поддерживается память, а все объекты являются объектами

ex a=5 здесь 5 хранится в ячейке памяти, а указатель на нее.

, так что если вы делаетеb=5 затем hex (id (a)) == hex (id (b)), оба объекта указывают на одну и ту же область памяти.

поэтому интерфейс такой:

объект Python - модуль указателя -> фактическая ячейка памяти

, поэтому, если вы измените значение a, скажем a = 53, то проверьте hex(id(a)) тогда вы обнаружите, что оно отличается от предыдущего, но объект тот же. так что мы можем сказать, что новое расположение mmory выполнено, выделение промежуточного объекта Python (не знаю, как это называется) обрабатывает присвоение (привязку) к новой ячейке памяти, и объект (a)

теперь задается вопросом, как долгоон поддерживает неназначенное значение 5 в памяти, все зависит от размера кучи, сколько может хранить распределитель мусора, c apis

...