Идентифицируя объекты, почему изменяется возвращаемое значение из id(...)?
Идентификатор (объект)
Это целое число (или длинное целое число), которое гарантированно будет уникальным и постоянным для этого объекта в течение срока его службы.
Можете ли вы объяснить этот вывод? Почему j
смена ID?
>>> i=10
>>> id(i)
6337824
>>> j=10
>>> id(j)
6337824
>>> j=j+1
>>> id(j)
6337800
>>> id(i)
6337824
8 ответов
Поскольку целые числа являются неизменяемыми, каждое целочисленное значение является отдельным объектом с уникальным идентификатором. Целое число 10
имеет другой идентификатор от 11
, дела j=j+1
не изменяет значение существующего целочисленного объекта, скорее оно меняет j
указывать на объект для 11
,
Узнайте, что происходит, когда мы независимо создаем новую переменную k
и назначьте ему значение 11
:
>>> j=10
>>> id(j)
8402204
>>> j=j+1
>>> id(j)
8402192
>>> k=11
>>> id(k)
8402192
Обратите внимание, что это не всегда тот случай, когда каждое целое число имеет один и только один соответствующий объект. Это происходит только для маленьких целых чисел, которые Python решает кэшировать. Это не происходит для больших целых чисел:
>>> x = 123456789
>>> id(x)
8404568
>>> y = 123456789
>>> id(y)
8404604
См. https://docs.python.org/3/c-api/long.html:
Текущая реализация хранит массив целочисленных объектов для всех целых чисел от -5 до 256, когда вы создаете int в этом диапазоне, вы на самом деле просто получаете ссылку на существующий объект.
Вот почему 2**8 is 2**8 == True
, а также 2**9 is 2**9 == False
,
Значения от -5 до 256 предварительно распределяются.
Такой же id
для разных переменных это продукт того, как Python создает переменные.
id
является хешем расположения объекта в памяти. Переменные Python - это ссылки на объект, а не новые объекты. Если несколько переменных ссылаются на один и тот же объект, они имеют одинаковый идентификатор.
В CPython id
как правило, происходит от Py_Object
Значение указателя, то есть его местоположение в памяти.
Python кэширует неизменяемые объекты (читайте целые числа и кортежи...) - вот почему они неизменяемы и экономят память, если во многих местах вы ссылаетесь на одну и ту же неизменяемую. Так small
целые числа, пустые кортежи и тому подобное фактически кэшируются во время выполнения Python, поэтому вы продолжаете получать один и тот же объект и, следовательно, один и тот же идентификатор.
Попробуйте это для списка, вы не получите тот же идентификатор.
j
ID изменяется, потому что объект, названный j
изменения. Сначала вы инициализируете j
до 10, поэтому, когда вы звоните id(j)
Вы получаете идентификатор 10
, Затем вы установите j
до 11, так что после этого, когда вы звоните id(j)
Вы получаете идентификатор 11
,
Дело в том, что каждый объект (значение) имеет уникальный идентификатор в Python, например объекты'hello'
и'hi'
иметь свои собственные идентификаторы или и11
есть еще 2 разных идентификатора. Другое дело, что каждая переменная — это просто метка для определенного объекта (значения). Теперь, когда мы говорим, идентификатор объекта присваивается переменной. Затем, когда вы меняете значение (например,j=j+1
), будет ссылаться на другой объект. Другими словами, станет меткой другого объекта. Таким образом, идентификатор меняется при изменении его значения. Существует также подход к кэшированию Python, который помогает ему быть более эффективным. Например, когда вы пишетеj=10
иx=10
вместо создания двух отдельных объектов создается только один объект10
с 2 этикеткамиj
иx
.
Это примитивные типы, поэтому я предполагаю, что каждое значение получает свой собственный идентификатор. Попробуйте создать настоящий объект, и я думаю, вы увидите ожидаемую функциональность.
Если вам нужен идентификатор для примитива, вы можете создать объект только с одним членом этого типа.