Python可变对象中的引用与赋值

时间:2014-01-13 13:52:32

标签: python reference variable-assignment

分配:

>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False

参考:

>>> c = ['spam']
>>> d = c
>>> c is d
True
  1. 上述两者有什么区别?
  2. 为什么分配结果为False
  3. 为何参考结果True

4 个答案:

答案 0 :(得分:9)

您的第一个代码段会创建两个唯一列表对象,这些对象不同。因此a is b返回false,因为ab指向不同的对象:

          +------+
a ------> | list |
          +------+

          +------+
b ------> | list |
          +------+

您的第二个代码段会创建一个列表对象,并将cd指向该对象,因此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.)