什么是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中的内存地址是同义词吗? 如果是这样,为什么整数不对应数据types的大小?
id()
用在实践中?
您的post提出了几个问题:
从函数返回的数字是多less?
它是“ 一个整数(或长整型),在其生命周期中保证这个对象是唯一且恒定的。 ” (Python标准库 – 内置函数)一个唯一的数字。 没有更多,也没有less。 将其视为Python对象的社会安全号码或员工身份号码。
与C中的内存地址是一样的吗?
从概念上说,是的,因为它们在一生中都保证它们在宇宙中是独一无二的。 在Python的一个特定实现中,它实际上是相应C对象的内存地址。
如果是的话,为什么这个数字不会立即增加数据types的大小(我认为它会是int)?
因为列表不是一个数组,列表元素是一个引用,而不是一个对象。
我们什么时候真的使用
id( )
函数?
几乎没有。 在is
运算符中使用id()
(或其等价物)。
这是对象在内存中的位置的标识…
这个例子可能会帮助你更多地理解这个概念。
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()
函数可以方便地创build不透明句柄,以便在从C中调用python
时返回C代码。这样做可以很容易地使用字典从句柄中查找对象,并且保证独特。
我开始与python和我使用id时,我使用交互式shell来查看我的variables是分配给相同的东西,或者他们只是看起来相同。
每个值都是一个id,它是一个唯一的数字,与它存储在计算机内存中的位置有关。
这是内存中的对象的地址,正如文档所说。 然而,它具有附加的元数据,对象的属性和存储器中的位置需要存储元数据。 所以,当你创build名为list的variables的时候,你还可以为列表及其元素创build元数据。
所以,除非你是语言上的绝对权威,否则你不能根据前一个元素来确定你的列表中下一个元素的id,因为你不知道这个语言与元素一起分配了什么。
答案是从来没有。 ID主要在Python内部使用。
普通的Python程序员可能永远不需要在他们的代码中使用id()
。
is
运算符使用它来检查两个对象是否相同(相当于相等)。 从id()
返回的实际值几乎从不用于任何事情,因为它没有真正意义,而且是依赖于平台的。
如果你正在使用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有一个不变的id,并且多次发现它的id不会改变,不同于之前或之后的所有其他数字,每当你findid时都有不同的id。 从-5到256的数字具有递增的顺序,相差16。
由id()函数返回的数字是存储在内存中的每个项目的唯一ID,它与C中的内存位置类似。
罗布的答案(上面大多数投票)是正确的。 我想补充一点,在某些情况下使用ID是有用的,因为它允许比较对象并找出哪些对象引用了你的对象。
后者通常可以帮助你debugging可变对象作为parameter passing给类的奇怪的错误,并被分配给类中的本地variables。 突变这些对象会改变class级中的variables。 这performance在多个事物同时变化的奇怪行为中。
最近我遇到了一个Python / Tkinter应用程序的问题,在一个文本input字段中编辑文本改变了另一个文本,因为我键入:)
这里是一个关于如何使用函数id()来跟踪那些引用的地方的例子。 无论如何,这不是涵盖所有可能情况的解决scheme,但你明白了。 再次在后台使用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'}
variables名中的下划线用于防止名称变形。 函数使用“fromwhere”参数,以便让他们知道从哪里开始search引用。 这个参数由一个列出给定名字空间中的所有名字的函数填充。 全局()是一个这样的function。
我有一个想法,在日志中使用id()的值。 这很便宜,而且很短。 在我的情况下,我使用龙卷风和ID()想有一个锚点,以分散和混合文件通过networking套接字的消息。