Python id() 函数是做什么用的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15667189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the id( ) function used for?
提问by Thanakron Tandavas
I read the Python 2 docsand noticed the id()function:
我阅读了 Python 2 文档并注意到了这个id()函数:
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.
返回对象的“身份”。这是一个整数(或长整数),保证在此对象的生命周期内是唯一且恒定的。生命周期不重叠的两个对象可能具有相同的 id() 值。
CPython 实现细节:这是对象在内存中的地址。
So, I experimented by using id()with a list:
因此,我通过使用id()列表进行了试验:
>>> 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?
从函数返回的整数是什么?它是 C 中内存地址的同义词吗?如果是这样,为什么整数不对应于数据类型的大小?
When is id()used in practice?
什么时候id()在实践中使用?
采纳答案by Rob?
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.
它是“一个整数(或长整数),在其生命周期内保证此对象的唯一性和常量。” (Python 标准库 - 内置函数)一个唯一的数字。没有更多,也没有更少。将其视为 Python 对象的社会保险号或员工 ID 号。
Is it the same with memory addresses in C?
与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.
从概念上讲,是的,因为他们都保证在他们的一生中在他们的宇宙中都是独一无二的。在 Python 的一种特定实现中,它实际上是对应 C 对象的内存地址。
If yes, why doesn't the number increase instantly by the size of the data type (I assume that it would be int)?
如果是,为什么数字不会立即增加数据类型的大小(我假设它是 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?
我们什么时候真正使用
id( )函数?
Hardly ever. id()(or its equivalent) is used in the isoperator.
几乎没有。id()(或其等价物)用于is运算符。
回答by brbcoding
That's the identity of the locationof 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, 1is only stored once, and anything else pointing to 1will reference that memory location.
这些都指向内存中的相同位置,这就是它们的值相同的原因。在示例中,1只存储一次,其他任何指向的内容都1将引用该内存位置。
回答by Gareth Latty
The answer is pretty much never. IDs are mainly used internally to Python.
答案几乎是永远不会。ID 主要在 Python 内部使用。
The average Python programmer will probably never need to use id()in their code.
一般的 Python 程序员可能永远不需要id()在他们的代码中使用。
回答by omz
The isoperator 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.
的is操作者使用它来检查两个对象是否是相同的(而不是相等)。返回的实际值id()几乎从未用于任何事情,因为它没有真正的意义,而且它依赖于平台。
回答by FatalError
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:
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]);
In other words, you are printing the address from the reference and notan 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 pythonfrom C. Doing that, you can easily use a dictionary to look up the object from its handle and it's guaranteed to be unique.
就我而言,我发现该id()函数可方便地创建不透明句柄,以便在python从 C调用时返回 C 代码。这样做,您可以轻松使用字典从句柄中查找对象,并保证它是唯一的。
回答by Lajos Arpad
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.
它是对象在内存中的地址,正如文档所说。但是,它附加了元数据,需要对象的属性和内存中的位置来存储元数据。因此,当您创建名为 list 的变量时,您还为列表及其元素创建了元数据。
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.
因此,除非您是该语言的绝对大师,否则您无法根据前一个元素确定列表中下一个元素的 id,因为您不知道该语言与元素一起分配了什么。
回答by Longtomjr
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.
我从 python 开始,当我使用交互式 shell 来查看我的变量是否分配给相同的东西或者它们看起来是否相同时,我使用 id 。
Every value is an id, which is a unique number related to where it is stored in the memory of the computer.
每个值都是一个 id,它是一个唯一的数字,与它在计算机内存中的存储位置有关。
回答by Dhvanan Shah
If you're using python 3.4.1 then you get a different answer to your question.
如果您使用的是 python 3.4.1,那么您的问题会得到不同的答案。
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 -5to 256have 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 -5to 256have id's in increasing order and differ by 16.
该整数-5到256具有恒定的ID和与之前或之后多次将其ID不改变,与所有其他号码找到它,它有不同的ID是每次都发现它的时候。从-5到256id 的数字按递增顺序排列并相差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.
id()函数返回的数字是为存储在内存中的每个项目赋予的唯一 id,它与 C 中的内存位置类似。
回答by Arijan
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.
Rob 的答案(上面投票最多)是正确的。我想补充一点,在某些情况下,使用 ID 很有用,因为它允许比较对象并找到哪些对象引用了您的对象。
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 :)
最近我在 Python/Tkinter 应用程序中遇到了这个问题,在我输入时,在一个文本输入字段中编辑文本会更改另一个文本输入字段中的文本:)
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:
这是一个关于如何使用函数 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()) )
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.
变量名称中的下划线用于防止名称冲突。函数使用“fromwhere”参数,这样你就可以让他们知道从哪里开始搜索引用。此参数由一个函数填充,该函数列出给定命名空间中的所有名称。Globals() 就是这样一种函数。
回答by Daneel S. Yaitskov
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.
我有一个想法id()在日志中使用值。
它很便宜,而且很短。
在我的情况下,我使用龙卷风,并id()希望有一个锚点来对通过网络套接字分散和混合在文件中的消息进行分组。

