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

Я прочитал документы Python 2 и заметил функцию 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() на практике?

Ответ 1

Ваше сообщение задает несколько вопросов:

Каково число, возвращаемое функцией?

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

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

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

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

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

Когда мы действительно используем функцию id( )?

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

Ответ 2

То, что идентификация местоположения объекта в памяти...

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

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 будет ссылаться на эту ячейку памяти.

Ответ 3

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. Выполняя это, вы можете легко использовать словарь для поиска объекта из его дескриптора, и это гарантировано уникальный.

Ответ 4

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

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

Ответ 5

Если вы используете 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 числа -5 до 256 имеют постоянный идентификатор, и при нахождении его несколько раз его идентификатор не изменяется, в отличие от всех других номеров до или после него, которые имеют разные идентификаторы каждый раз, когда вы его находите. Числа из -5 до 256 имеют id в порядке возрастания и отличаются на 16.

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

Ответ 6

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

Позднее обычно помогает вам, например, отлаживать странные ошибки, когда изменяемые объекты передаются как параметр для обозначения классов и назначаются локальным варам в классе. Мутирование этих объектов будет мутировать 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() - одна из таких функций.

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

Ответ 10

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

Ответ 11

хорошо, если это что-то, убедитесь, что вы определили слово, прежде чем использовать его. это все о цепях

Ответ 12

Начиная с Python 3, идентификатор присваивается значению, а не переменной. Это означает, что если вы создадите две функции, как показано ниже, все три идентификатора будут одинаковыми.

>>> def xyz():
...     q=123
...     print(id(q))
...
>>> def iop():
...     w=123
...     print(id(w))
>>> xyz()
1650376736
>>> iop()
1650376736
>>> id(123)
1650376736