Для чего используется функция id ()?


я прочитала Python 2 docs и увидел id() функция:

возвращает "идентичность" объекта. Это целое число (или длинное целое число), которое гарантированно будет уникальным и постоянным для этого объекта в течение его жизни. Два объекта с неперекрывающимися жизненными циклами могут иметь одинаковое значение id ().

CPython деталь реализации: это адрес объекта в памяти.

Итак, я экспериментировал с использованием id() список:

>>> list = [1,2,3]
>>> id(list[0])
31186196
>>> id(list[1])
31907092 // increased by 896
>>> id(list[2])
31907080 // decreased by 12

какое целое число возвращается из функции? Является ли это синонимом адресов памяти в C? Если да, то почему целое число не соответствует размеру типа данных?

когда id() используется на практике?

10 72

10 ответов:

ваш пост задает ряд вопросов:

какое число возвращается из функции?

Это "целое число (или длинное целое число), которое гарантированно будет уникальным и постоянным для этого объекта в течение его жизни."(стандартная библиотека Python-встроенные функции) уникальный номер. Ни больше, ни меньше. Подумайте об этом как о номере социального страхования или идентификационном номере сотрудника для объектов Python.

то же самое с адресами памяти в C?

концептуально, да, в том, что оба они уникальны в своей вселенной в своей жизни. И в одной конкретной реализации Python это фактически адрес памяти соответствующего объекта C.

Если да, то почему число не увеличивается мгновенно на размер типа данных (я предполагаю, что это будет int)?

потому что список-это не массив, и элемент списка является ссылкой, а не объектом.

когда мы действительно использовать ?

вряд ли когда-нибудь. id() (или эквивалент) используется в is оператора.

Это личность расположение объекта в памяти...

этот пример может помочь вам понять концепцию немного больше.

foo = 1
bar = foo
baz = bar
fii = 1

print id(foo)
print id(bar)
print id(baz)
print id(fii)

> 1532352
> 1532352
> 1532352
> 1532352

все то же место в памяти, поэтому их значения одинаковы. В Примере,1 хранится только один раз, и все остальное, указывая на 1 будет ссылаться на эту область памяти.

id() возвращает адрес объекта, на который ссылается (в CPython), но ваша путаница связана с тем, что списки python очень отличаются от массивов C. В списке python каждый элемент является ссылка. Так что то, что вы делаете, гораздо больше похоже на этот код C:

int *arr[3];
arr[0] = malloc(sizeof(int));
*arr[0] = 1;
arr[1] = malloc(sizeof(int));
*arr[1] = 2;
arr[2] = malloc(sizeof(int));
*arr[2] = 3;
printf("%p %p %p", arr[0], arr[1], arr[2]);

иными словами, вы печатаете адрес из ссылки и не адрес относительно того, где хранится ваш список.

в моем случае, я нашли то id() функция удобна для создания непрозрачных дескрипторов для возврата к коду C при вызове python от C. делая это, вы можете легко использовать словарь для поиска объекта из его дескриптора, и он гарантированно будет уникальным.

Я начинаю с python, и я использую id, когда я использую интерактивную оболочку, чтобы увидеть, назначены ли мои переменные одной и той же вещи или они просто выглядят одинаково.

каждое значение является идентификатором, который является уникальным номером, связанным с тем, где он хранится в памяти компьютера.

ответ Роба (большинство проголосовало выше) является правильным. Я хотел бы добавить, что в некоторых ситуациях использование идентификаторов полезно, поскольку оно позволяет сравнивать объекты и находить, какие объекты относятся к вашим объектам.

последнее обычно помогает вам, например, отлаживать странные ошибки, когда изменяемые объекты передаются в качестве параметра, чтобы сказать классы и назначаются локальным vars в классе. Мутация этих объектов приведет к мутации vars в классе. Это проявляется в странном поведении, когда несколько все меняется одновременно.

недавно у меня была эта проблема с приложением Python/Tkinter, где редактирование текста в одном поле ввода текста изменило текст в другом, когда я набрал:)

вот пример того, как вы можете использовать функцию id() для отслеживания, где находятся эти ссылки. Конечно, это не решение, охватывающее все возможные случаи, но вы получите идею. Снова идентификаторы используются в фоновом режиме и пользователь не видит они:

class democlass:
    classvar = 24

    def __init__(self, var):
        self.instancevar1 = var
        self.instancevar2 = 42

    def whoreferencesmylocalvars(self, fromwhere):
        return {__l__: {__g__
                    for __g__ in fromwhere
                        if not callable(__g__) and id(eval(__g__)) == id(getattr(self,__l__))
                    }
                for __l__ in dir(self)
                    if not callable(getattr(self, __l__)) and __l__[-1] != '_'
                }

    def whoreferencesthisclassinstance(self, fromwhere):
        return {__g__
                    for __g__ in fromwhere
                        if not callable(__g__) and id(eval(__g__)) == id(self)
                }

a = [1,2,3,4]
b = a
c = b
democlassinstance = democlass(a)
d = democlassinstance
e = d
f = democlassinstance.classvar
g = democlassinstance.instancevar2

print( 'My class instance is of', type(democlassinstance), 'type.')
print( 'My instance vars are referenced by:', democlassinstance.whoreferencesmylocalvars(globals()) )
print( 'My class instance is referenced by:', democlassinstance.whoreferencesthisclassinstance(globals()) )

выход:

My class instance is of <class '__main__.democlass'> type.
My instance vars are referenced by: {'instancevar2': {'g'}, 'classvar': {'f'}, 'instancevar1': {'a', 'c', 'b'}}
My class instance is referenced by: {'e', 'd', 'democlassinstance'}

подчеркивания в именах переменных используются для предотвращения коллизий имен. Функции используют аргумент" fromwhere", чтобы вы могли сообщить им, с чего начать поиск ссылок. Этот аргумент заполняется функцией, которая перечисляет все имена в данном пространстве имен. Globals () является одной из таких функций.

если вы используете python 3.4.1, то вы получите другой ответ на свой вопрос.

list = [1,2,3]
id(list[0])
id(list[1])
id(list[2])

возвращает:

1705950792   
1705950808  # increased by 16   
1705950824  # increased by 16

чисел -5 до 256 имеют постоянный идентификатор, и при поиске его несколько раз его идентификатор не меняется, в отличие от всех других чисел до или после него, которые имеют разные идентификаторы каждый раз, когда вы его находите. Цифры от -5 до 256 есть ID в порядке возрастания и отличаются 16.

число, возвращенное id() функция-это уникальный идентификатор, заданный каждому элементу, хранящемуся в памяти, и он аналогичен тому же месту памяти в C.

Это адрес объекта в памяти, точно так, как доктор говорит. Однако к нему прикреплены метаданные, свойства объекта и расположение в памяти необходимы для хранения метаданных. Таким образом, при создании переменной с именем list вы также создаете метаданные для списка и его элементов.

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

ответ в значительной степени никогда. Идентификаторы в основном используются внутри Python.

средний программист Python, вероятно, никогда не будет использовать id() в своем коде.

The is оператор использует его, чтобы проверить, являются ли два объекта идентичны (в отличие от равных). Фактическое значение, возвращаемое из id() почти никогда не используется ни для чего, потому что это действительно не имеет смысла, и это зависит от платформы.

у меня есть идея использовать значение id() на лесозаготовках.
Это дешево, чтобы получить, и это довольно коротко.
В моем случае я использую "торнадо" и id() хотел бы иметь якорь для группировки сообщений, разбросанных и смешанных по файлу с помощью веб-сокета.