比较python中两个变量是否引用同一对象

比较python中两个变量是否引用同一对象,python,Python,如何检查两个变量是否引用同一对象 x = ['a', 'b', 'c'] y = x # x and y reference the same object z = ['a', 'b', 'c'] # x and z reference different objects 这就是为什么 在本例中,x是y返回True,因为它是同一个对象,x是z返回False,因为它是不同的对象(恰好包含相同的数据)。y是x将是True,y是z将是False您还可以使用它来检查

如何检查两个变量是否引用同一对象

x = ['a', 'b', 'c']
y = x                 # x and y reference the same object
z = ['a', 'b', 'c']   # x and z reference different objects
这就是为什么


在本例中,
x是y
返回
True
,因为它是同一个对象,
x是z
返回
False
,因为它是不同的对象(恰好包含相同的数据)。

y是x
将是
True
y是z
将是
False

您还可以使用它来检查每个变量名引用的唯一对象

In [1]: x1, x2 = 'foo', 'foo'

In [2]: x1 == x2
Out[2]: True

In [3]: id(x1), id(x2)
Out[3]: (4509849040, 4509849040)

In [4]: x2 = 'foobar'[0:3]

In [5]: x2
Out[5]: 'foo'

In [6]: x1 == x2
Out[6]: True

In [7]: x1 is x2
Out[7]: False

In [8]: id(x1), id(x2)
Out[8]: (4509849040, 4526514944)

虽然已经发布了两个正确的解决方案
x是z
id(x)==id(z)
,但我想指出python的一个实现细节。Python将整数存储为对象,作为一种优化,它在开始时生成一组小整数(-5到256),并将每个包含一个小值整数的变量指向这些预初始化的对象

这意味着,对于初始化为相同小数字(-5到256)的整数对象,检查两个对象是否相同将返回true(就我所知,这是一个实现细节),而对于较大的数字,仅当一个对象从另一个对象初始化时才返回true

> i = 13
> j = 13
> i is j
True

> a = 280
> b = 280
> a is b
False

> a = b
> a
280
> a is b
True

我真的很喜欢有一个视觉反馈,这就是为什么我有时只是打开看看内存是如何分配的,什么是引用什么


添加了这个很棒的gif,因为这个回复是关于可视化的。

这是来自docs.python.org的:“每个对象都有一个标识、一个类型和一个值。一个对象的标识在创建后永远不会更改;您可以将其视为对象在内存中的地址。'is'操作符比较两个对象的标识;id()函数返回一个表示其标识的整数。“


显然,每次更改值时,都会按照标识更改指示重新创建对象。第x=3行后跟第x=3.14行没有错误,并为x提供了不同的标识、类型和值。

在示例中,
x是z
返回
False
。但是如果x和z被分配了相同的值而不是列表(例如
x,z=13,13
),那么
x是z
返回
True
。这是为什么?@Bill:这是python处理int的人工制品。Python将整数对象分配给
x
z
指向的对象。由于小整数是非常常见的(-1作为错误值,0任何时候实际索引某些内容,小数字通常是合理的默认值),Python通过预分配小数字(-5到256)进行优化,并重用相同的整数对象。因此,您的示例仅适用于此范围内的数字。尝试分配更大的值,即
270
。有关更多信息,请查看@AndresR No,这是错误的
is
检查两个名称是否引用相同的内存位置。它与对象本身无关。像字符串这样的不可变对象是很容易的,它们是相等的,但不存储在同一个位置,例如
“a”*10000是“a”*10000
是False。@JochenRitzel你完全正确,谢谢你的评论!所以,我不明白在
“af”是“af”
还是
()是()
。。。为什么它们共享相同的内存位置?@AndreasR对于代码中的文字字符串/数字,编译器会检查它们是否只存在一次并重用它们。特殊值,如()、None、True、False等也被定义为单例。在执行过程中,运行时也会尝试重用少量的数字和字符串,但最终这是速度和内存之间的折衷,发生了什么取决于Python运行时的实现方式;b=98765;a是b=>真的。“显然有些事情改变了。”米哈伊尔·卡拉什尼科夫说。我在Python3.6.2上测试过,它仍然存在。在Python3.7.7上仍然存在优秀的doc catch。
x
是标识值为
3
的对象的名称,而不是对象本身。当您执行
x=3.14
时,您没有更改以前由
x
标识的对象-您更改了名称
x
所指的对象。@ted关于id使用的说明与此非常相关。