分配:
>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False
参考:
>>> c = ['spam']
>>> d = c
>>> c is d
True
False
?True
?答案 0 :(得分:9)
您的第一个代码段会创建两个唯一列表对象,这些对象不同。因此a is b
返回false,因为a
和b
指向不同的对象:
+------+ a ------> | list | +------+ +------+ b ------> | list | +------+
您的第二个代码段会创建一个列表对象,并将c
和d
指向该对象,因此c is d
将返回true:
+------+ c ------> | list | <------ d +------+
请注意以下内容,来自http://docs.python.org/3/reference/datamodel.html:
每个对象都有一个标识,一个类型和一个值。对象的标识一旦创建就永远不会改变;您可能会将其视为内存中对象的地址。
is
运算符比较两个对象的标识;id()
函数返回一个表示其身份的整数。
所以is
和==
非常不同;前者比较对象标识,后者比较对象值。实际上,您的片段中的==
测试将返回true。
鉴于上面的解释,这个故事与字符串略有不同可能会让人感到惊讶:
>>> a = 'str'
>>> b = 'str'
>>>
>>> a is b
True
这是由string interning引起的,它发生在CPython中(即它是特定于实现的)。因此,如果相同的字符串文字显示在两个不同的位置,则同一个字符串对象将用于两者(有限制)。
"Python string interning"中详细解释了这一点。
答案 1 :(得分:4)
与is
比较时,与a is b
相同,与id(a) == id(b)
相同,代码xx=['spam']
每次都会创建一个新列表并将其分配给xx
},id
每次都会更改,因此a is b
会给出错误
答案 2 :(得分:2)
这与某些(不存在的)“分配与引用”问题无关。
>>> a = ['spam']
创建一个包含字符串'spam'的列表,并将其绑定到当前范围中的名称'a'。
>>> b = ['spam']
在其中创建另一个包含字符串'spam'的列表,并将其绑定到当前范围中的名称'b'。
您创建了两个列表,您有两个列表。简单明了。
>>> c = ['spam']
在其中创建另一个包含字符串'spam'的列表,并将其绑定到当前范围中的名称'c'。
>>> d = c
将名称“d”绑定到当前范围内当前绑定的“c”。
在这里,您可以创建一个列表并为其绑定2个名称。两个名称都指向同一个对象。
重点是:Python的“变量”不是命名的内存地址,只是指向对象的名称。在给定的时间,一个对象可以绑定(指向)任意数量的名称(甚至根本没有名称)。
答案 3 :(得分:1)
让我给你原来做的事情添加几个函数调用。我想你会接受它。
>>> 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.)