id()函数用于什么?

Tha*_*vas 93 python

我阅读了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
Run Code Online (Sandbox Code Playgroud)

函数返回的整数是多少?它是C中内存地址的同义词吗?如果是这样,为什么整数不对应于数据类型的大小?

何时id()在实践中使用?

Rob*_*obᵩ 144

您的帖子提出了几个问题:

函数返回的数字是多少?

它是" 一个整数(或长整数),保证在该生命周期内对于该对象是唯一的和常量的. " (Python标准库 - 内置函数)一个唯一的数字.没有更多,也没有更少.将其视为Python对象的社会安全号码或员工ID号.

与C中的内存地址相同吗?

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

如果是,为什么数字不会立即增加数据类型的大小(我假设它将是int)?

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

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

几乎没有.id()(或其等效物)用于is操作员.

  • 我们通常在演示目的中使用 id(),如下所示 /sf/ask/1207268541/ Between-shallow-copy-deepcopy-and-normal-assignm (2认同)

brb*_*ing 50

这是对象在内存中的位置的身份......

这个例子可能会帮助您更多地理解这个概念.

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

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

> 1532352
> 1532352
> 1532352
> 1532352
Run Code Online (Sandbox Code Playgroud)

这些都指向内存中的相同位置,这就是它们的值相同的原因.在该示例中,1仅存储一次,并且指向的任何其他内容1将引用该存储器位置.

  • 但是如果使用-5到256范围之外的数字,则fii变量不会获得相同的id. (8认同)
  • 我认为这个答案具有误导性,因为这不适用于大多数数字;请参阅[“is”运算符对整数的行为异常](/sf/ask/21441941/)。 (4认同)

小智 10

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

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

最近我在 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()) )
Run Code Online (Sandbox Code Playgroud)

输出:

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'}
Run Code Online (Sandbox Code Playgroud)

变量名称中的下划线用于防止名称冲突。函数使用“fromwhere”参数,这样你就可以让他们知道从哪里开始搜索引用。此参数由一个函数填充,该函数列出给定命名空间中的所有名称。Globals() 就是这样一种函数。


Fat*_*ror 8

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]);
Run Code Online (Sandbox Code Playgroud)

换句话说,您将从引用中打印地址,而不是相对于列表存储位置的地址.

在我的例子中,我发现id()函数很方便用于创建不透明的句柄,以便在python从C 调用时返回到C代码.这样,您可以轻松地使用字典从其句柄中查找对象,并保证它是唯一的.


Lon*_*mjr 5

我开始使用python并且当我使用交互式shell来查看我的变量是否被分配给同一个东西或者它们看起来是否相同时我使用id.

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


小智 5

如果您使用的是python 3.4.1,那么您会得到一个不同的答案。

list = [1,2,3]
id(list[0])
id(list[1])
id(list[2])
Run Code Online (Sandbox Code Playgroud)

返回:

1705950792   
1705950808  # increased by 16   
1705950824  # increased by 16
Run Code Online (Sandbox Code Playgroud)

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

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