理解Python引用

时间:2014-01-12 16:01:06

标签: python

鉴于python中的所有内容都是通过引用,我确实理解下面的代码中发生了什么:

a = ['one']*3       // a = ['one', 'one', 'one']
b = [a]*3           // b = [['one', 'one', 'one'], ['one', 'one', 'one'], ['one', 'one', 'one']]
b[1][2] = 'two'  

现在,b是

[['one', 'one', 'two'], ['one', 'one', 'two'], ['one', 'one', 'two']]

因为我们将b引用了a引用的相同对象的三倍,重新分配任何一个组件,所以在三个位置都会看到更改。

但是,为什么同样的事情发生在

a = [['one']]*3        // a = [['one'], ['one'], ['one']]
a[1] = ['two']        

不会生成a = ['two', 'two', 'two'],而只会生成[['one'], ['two'], ['one'],好像现在有三个不同的对象指向。

我在这里错过了一些逻辑吗?

提前致谢, NIKHIL

3 个答案:

答案 0 :(得分:3)

您没有更改a[1]的内容,而是将其重新绑定以指向单独的数组。这对a[0]a[2]无效。

请尝试以下方法:

In [4]: a = [['one']]*3

In [5]: a[1][0] = 'two'

In [6]: a
Out[6]: [['two'], ['two'], ['two']]

答案 1 :(得分:1)

我发现理解引用如何工作的最好方法是在Python Tutor通过模拟器运行它们(单击该链接将运行上面的示例)。这使情况非常清楚。这也值得一读this article

答案 2 :(得分:1)

要记住的一件重要事情是,对象具有存在性和独立于指向它们的名称的身份;并且x = y 意味着“将x指向的对象的值更改为y指向的内容”。这意味着“将x指向y指向的内容”。

使用id可能有助于澄清正在发生的事情:

>>> a = [['one']]*3
>>> (id(a[0]), id(a[1]), id(a[2]))
(140193404836320, 140193404836320, 140193404836320)
>>> a[1] = ['two']
>>> (id(a[0]), id(a[1]), id(a[2]))
(140193404836320, 140193368088088, 140193404836320)

最初,a[0]a[1]a[2]都是同一个对象,正如人们所期望的那样:

       +------+------+------+
  a -->|      |      |      |
       +------+------+------+
            \    |     /
             |   |     |
             v   v     v
             +---------+
             | ['one'] |
             +---------+

然后a[1] = ['two']使a[1]指向一个新对象:

       +------+------+------+
  a -->|      |      |      |
       +------+------+------+
         |       |      |
         |       |      |
         |       |      |
         |       v      |
         |  +---------+ |
         |  | ['two'] | |
         |  +---------+ |
         |              |
         |  +---------+ | 
         \> | ['one'] |</
            +---------+   

请注意,该图表已经过简化,以显示要点,['one']['two']不是图中显示的简单值。