问题: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()在实践中何时使用?

I read the Python 2 docs and noticed the id() function:

Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

CPython implementation detail: This is the address of the object in memory.

So, I experimented by using id() with a list:

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

What is the integer returned from the function? Is it synonymous to memory addresses in C? If so, why doesn’t the integer correspond to the size of the data type?

When is id() used in practice?


回答 0

您的帖子问了几个问题:

该函数返回的数字是多少?

它是“ 一个整数(或长整数),该整数在该对象的生存期内保证是唯一且恒定的。(Python标准库-内置函数)一个唯一的数字。仅此而已。可以将其视为Python对象的社会保险号或员工ID号。

与C中的内存地址是否相同?

从概念上讲,是的,因为它们在生命周期中都被保证在宇宙中是独一无二的。在Python的一种特定实现中,它实际上是相应C对象的内存地址。

如果是,为什么数字不立即随数据类型的大小增加(我认为是整数)?

因为列表不是数组,列表元素是引用,而不是对象。

我们什么时候真正使用id( )功能?

几乎没有。id()(或其等效项)在is运算符中使用。

Your post asks several questions:

What is the number returned from the function?

It is “an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime.(Python Standard Library – Built-in Functions) A unique number. Nothing more, and nothing less. Think of it as a social-security number or employee id number for Python objects.

Is it the same with memory addresses in C?

Conceptually, yes, in that they are both guaranteed to be unique in their universe during their lifetime. And in one particular implementation of Python, it actually is the memory address of the corresponding C object.

If yes, why doesn’t the number increase instantly by the size of the data type (I assume that it would be int)?

Because a list is not an array, and a list element is a reference, not an object.

When do we really use id( ) function?

Hardly ever. id() (or its equivalent) is used in the is operator.


回答 1

那就是对象在内存中位置的标识…

这个例子可以帮助您更多地了解这个概念。

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将引用该内存位置。

That’s the identity of the location of the object in memory…

This example might help you understand the concept a little more.

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

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

> 1532352
> 1532352
> 1532352
> 1532352

These all point to the same location in memory, which is why their values are the same. In the example, 1 is only stored once, and anything else pointing to 1 will reference that memory location.


回答 2

id()确实返回(在CPython中)被引用对象的地址,但是您的困惑来自于事实,即python列表与C数组有很大的不同。在python列表中,每个元素都是reference。因此,您正在执行的操作与此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()函数非常方便创建python从C 调用时返回C代码的不透明句柄。这样做,您可以轻松地使用字典从其句柄中查找对象,并且保证它是唯一的。

id() does return the address of the object being referenced (in CPython), but your confusion comes from the fact that python lists are very different from C arrays. In a python list, every element is a reference. So what you are doing is much more similar to this C code:

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]);

In other words, you are printing the address from the reference and not an address relative to where your list is stored.

In my case, I have found the id() function handy for creating opaque handles to return to C code when calling python from C. Doing that, you can easily use a dictionary to look up the object from its handle and it’s guaranteed to be unique.


回答 3

罗伯的答案(上面投票最多)是正确的。我想补充一点,在某些情况下,使用ID很有用,因为它允许比较对象并查找哪些对象引用了您的对象。

后者通常可以帮助您调试奇怪的错误,例如,将可变对象作为参数传递给类,然后将其分配给类中的本地var。突变那些对象将突变一个类中的变量。这表现为多种行为同时改变的奇怪行为。

最近,我在Python / Tkinter应用程序中遇到了这个问题,该应用程序在一个文本输入字段中编辑文本会在我键入时更改另一个文本中的文本:)

这是一个示例,说明如何使用函数id()来跟踪这些引用的位置。无论如何,这不是涵盖所有可能情况的解决方案,但是您明白了。再次在后台使用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()就是这样一种功能。

Rob’s answer (most voted above) is correct. I would like to add that in some situations using IDs is useful as it allows for comparison of objects and finding which objects refer to your objects.

The later usually helps you for example to debug strange bugs where mutable objects are passed as parameter to say classes and are assigned to local vars in a class. Mutating those objects will mutate vars in a class. This manifests itself in strange behavior where multiple things change at the same time.

Recently I had this problem with a Python/Tkinter app where editing text in one text entry field changed the text in another as I typed :)

Here is an example on how you might use function id() to trace where those references are. By all means this is not a solution covering all possible cases, but you get the idea. Again IDs are used in the background and user does not see them:

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()) )

OUTPUT:

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'}

Underscores in variable names are used to prevent name colisions. Functions use “fromwhere” argument so that you can let them know where to start searching for references. This argument is filled by a function that lists all names in a given namespace. Globals() is one such function.


回答 4

我从python开始,在使用交互式外壳程序查看变量是否分配给相同的东西或它们看起来是否相同时,我使用id。

每个值都是一个id,它是一个唯一的数字,与它在计算机内存中的存储位置有关。

I am starting out with python and I use id when I use the interactive shell to see whether my variables are assigned to the same thing or if they just look the same.

Every value is an id, which is a unique number related to where it is stored in the memory of the computer.


回答 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

该整数-5256具有恒定的ID和与之前或之后多次将其ID不改变,与所有其他号码找到它,它有不同的ID是每次都发现它的时候。从-5256ID的数字按升序排列,且相差16

id()函数返回的数字是赋予存储在内存中的每个项目的唯一ID,从逻辑上讲,它与C中的存储位置相同。

If you’re using python 3.4.1 then you get a different answer to your question.

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

returns:

1705950792   
1705950808  # increased by 16   
1705950824  # increased by 16

The integers -5 to 256 have a constant id, and on finding it multiple times its id does not change, unlike all other numbers before or after it that have different id’s every time you find it. The numbers from -5 to 256 have id’s in increasing order and differ by 16.

The number returned by id() function is a unique id given to each item stored in memory and it is analogy wise the same as the memory location in C.


回答 6

答案几乎永远不会。ID主要在Python内部使用。

一般的Python程序员可能永远都不需要id()在他们的代码中使用。

The answer is pretty much never. IDs are mainly used internally to Python.

The average Python programmer will probably never need to use id() in their code.


回答 7

is操作者使用它来检查两个对象是否是相同的(而不是相等)。从中返回的实际值id()几乎没有用到任何东西,因为它没有真正的意义,并且与平台有关。

The is operator uses it to check whether two objects are identical (as opposed to equal). The actual value that is returned from id() is pretty much never used for anything because it doesn’t really have a meaning, and it’s platform-dependent.


回答 8

确切地说,它是对象在内存中的地址。但是,它具有附加的元数据,需要对象的属性和在存储器中的位置来存储元数据。因此,当您创建名为list的变量时,还将为该列表及其元素创建元数据。

因此,除非您是该语言的绝对专家,否则您将无法基于前一个元素确定列表中下一个元素的ID,因为您不知道该语言与元素一起分配了什么。

It is the address of the object in memory, exactly as the doc says. However, it has metadata attached to it, properties of the object and location in the memory is needed to store the metadata. So, when you create your variable called list, you also create metadata for the list and its elements.

So, unless you an absolute guru in the language you can’t determine the id of the next element of your list based on the previous element, because you don’t know what the language allocates along with the elements.


回答 9

我有一个id()在日志记录中使用值的想法。
它很便宜,而且很短。
以我为例,我使用龙卷风,并且id()希望有一个锚点来对通过Web套接字分散并混合在文件中的消息进行分组。

I have an idea to use value of id() in logging.
It’s cheap to get and it’s quite short.
In my case I use tornado and id() would like to have an anchor to group messages scattered and mixed over file by web socket.


回答 10

从python 3开始,id被分配给一个值而不是一个变量。这意味着,如果您按以下方式创建两个函数,则三个ID都相同。

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

As of in python 3 id is assigned to a value not a variable. This means that if you create two functions as below, all the three id’s are the same.

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

回答 11

我有点晚了,我将谈论Python3。要了解id()是什么以及它(和Python)如何工作,请考虑下一个示例:

>>> x=1000
>>> y=1000
>>> id(x)==id(y)
False
>>> id(x)
4312240944
>>> id(y)
4312240912
>>> id(1000)
4312241104
>>> x=1000
>>> id(x)
4312241104
>>> y=1000
>>> id(y)
4312241200

您需要将右侧的所有内容都视为对象。每次进行分配时,您都会创建一个新对象,这意味着新的ID。在中间,您可以看到仅为函数id(1000)创建的“野生”对象。因此,生命周期仅适用于该行代码。如果检查下一行-您会看到当我们创建新变量x时,它具有与该野生对象相同的ID。它几乎像内存地址一样工作。

I’m a little bit late and i will talk about Python3. To understand what id() is and how it (and Python) works, consider next example:

>>> x=1000
>>> y=1000
>>> id(x)==id(y)
False
>>> id(x)
4312240944
>>> id(y)
4312240912
>>> id(1000)
4312241104
>>> x=1000
>>> id(x)
4312241104
>>> y=1000
>>> id(y)
4312241200

You need to think about everything on the right side as objects. Every time you make assignment – you create new object and that means new id. In the middle you can see a “wild” object which is created only for function – id(1000). So, it’s lifetime is only for that line of code. If you check the next line – you see that when we create new variable x, it has the same id as that wild object. Pretty much it works like memory address.


回答 12

注意(关于下面的答案)…这是真的,因为123在-5到256之间…

In [111]: q = 257                                                         

In [112]: id(q)                                                            
Out[112]: 140020248465168

In [113]: w = 257                                                         

In [114]: id(w)                                                           
Out[114]: 140020274622544

In [115]: id(257)                                                         
Out[115]: 140020274622768

Be carefull (concerning the answer just below)…That’s only true because 123 is between -5 and 256…

In [111]: q = 257                                                         

In [112]: id(q)                                                            
Out[112]: 140020248465168

In [113]: w = 257                                                         

In [114]: id(w)                                                           
Out[114]: 140020274622544

In [115]: id(257)                                                         
Out[115]: 140020274622768

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。