【发布时间】:2023-03-10 17:09:02
【问题描述】:
作业:
>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False
参考:
>>> c = ['spam']
>>> d = c
>>> c is d
True
- 以上两者有什么区别?
- 为什么分配结果
False? - 为什么要参考结果
True?
【问题讨论】:
标签: python reference variable-assignment
作业:
>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False
参考:
>>> c = ['spam']
>>> d = c
>>> c is d
True
False?True?【问题讨论】:
标签: python reference variable-assignment
您的第一个 sn-p 创建了 两个 唯一的列表对象,它们并不相同。因此 a is b 返回 false 因为 a 和 b 指向不同的对象:
您的第二个 sn-p 创建一个列表对象,并将 c 和 d 指向该对象,因此 c is d 返回 true:
请注意以下内容,来自http://docs.python.org/3/reference/datamodel.html:
每个对象都有一个标识、一个类型和一个值。对象的身份一旦创建就永远不会改变;您可能会将其视为对象在内存中的地址。
is运算符比较两个对象的身份;id()函数返回一个表示其标识的整数。
所以is 和== 是非常不同的;前者比较对象身份,后者比较对象值。实际上,您的 sn-ps 中的 == 测试会返回 true。
鉴于上面的解释,故事与字符串略有不同可能会让人感到惊讶:
>>> a = 'str'
>>> b = 'str'
>>>
>>> a is b
True
这是由于string interning,它发生在 CPython 中(即它是特定于实现的)。因此,如果相同的字符串字面量出现在两个不同的位置,则相同的字符串对象将用于两者(有限制)。
这在"Python string interning"中有更详细的解释。
【讨论】:
spam 这样的不可变对象而不是 list ['spam'],为什么两者的结果都是 True
当与is比较时,如a is b,与id(a) == id(b)相同,代码xx=['spam']每次创建一个新列表并分配给xx,id每次都会变化,所以a is b 给出 False
【讨论】:
让我在您最初所做的工作中添加一些函数调用。我想你会捡起来的。
>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False
>>> id(a)
4552359808
>>> id(b)
4552446176
>>> a == b
True
>>> c = ['spam']
>>> d = c
>>> id(c)
4552513296
>>> id(d)
4552513296
>>> c is d
True
>>> c == d
True
>>> print id.__doc__
id(object) -> integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
【讨论】:
这与一些(不存在的)“分配与参考”问题无关。
>>> a = ['spam']
创建一个包含字符串“spam”的列表,并将其绑定到当前范围内的名称“a”。
>>> b = ['spam']
创建另一个包含字符串“spam”的列表,并将其绑定到当前范围内的名称“b”。
你创建了两个列表,你有两个列表。很简单。
>>> c = ['spam']
创建另一个列表,其中包含字符串“spam”,并将其绑定到当前范围内的名称“c”。
>>> d = c
将名称“d”绑定到当前范围内当时绑定的任何“c”。
在这里,您创建一个列表并将 2 个名称绑定到它。两个名称都指向同一个对象。
重点是:Python 的“变量”不是命名的内存地址,只是指向对象的名称。在给定时间,一个对象可以绑定(指向)任意数量的名称(甚至根本没有名称)。
【讨论】: