1

为什么以下代码会更改两个变量:

>>> a = []
>>> b = a
>>> a.append(9)
>>> a
[9]
>>> b
[9]
>>> 

但是del语句没有达到同样的效果?

>>> a = []
>>> b = a
>>> del(a)
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b
[]
>>> 
4

4 回答 4

2

当你这样做时:

a = b

您正在做的是将标签分配给标签所指b的同一对象a

当你这样做时:

a.append(9)

您正在添加9到由a和指向的列表对象b。这是同一个对象,所以它们显示相同的结果。

当你这样做时:

del a

您正在删除对对象的引用,而不是对象本身。如果它是唯一的引用,那么该对象将被垃圾收集。但是在您的情况下,还有另一个参考b--因此该对象继续存在。

于 2014-04-30T00:17:59.307 回答
1

考虑名称和对象,而不是“变量”。

>>> a = []

这将创建一个空列表对象并将名称绑定a到它。

>>> b = a

这只是说b现在是由 命名的对象的新名称a。我们有

>>> a is b
True

del a意味着我们忘记了名称a:它不再绑定到一个对象。

>>> del a
>>> a
Traceback (most recent call last):
  File "<ipython-input-8-60b725f10c9c>", line 1, in <module>
    a
NameError: name 'a' is not defined

但是您不再调用该 list object a, onlyb不会以任何方式影响对象本身。对象不关心,甚至不知道你给它们起什么名字。[一个半例外是,如果一个对象不再有任何引用,它可能——也可能不是,没有承诺——被垃圾收集。]

于 2014-04-30T00:17:59.827 回答
0

append方法对实际对象del起作用,而对引用即变量名起作用。

于 2014-04-30T00:17:47.000 回答
0

(我已经在你的另一个问题中回答了这个问题,所以我也将在这里使用它,稍作修改:)

del不删除对象;事实上,在 Python 中,甚至不可能告诉解释器/VM 从内存中删除对象,因为 Python 是一种垃圾收集语言(如 Java、C#、Ruby、Haskell 等)。

相反,del当调用一个变量(而不是字典键或列表项)时会发生什么,如下所示:

del a

它只删除了局部(或全局)变量,而不是它指向的变量(Python 中的每个变量都持有指向其内容的指针/引用,而不是内容本身)。事实上,由于局部变量和全局变量在底层存储为字典(请参阅locals()globals()),del a相当于:

del locals()['a']

(或del globals()['a']应用于全局时。)

所以如果你有:

a = []
b = a

您正在制作一个列表,将对其的引用存储在其中a,然后将该引用复制到其中,b而无需复制/触摸列表对象本身。因此,这两个调用影响同一个对象:

>>> a.append(1)
>>> b.append(2)
>>> a
[1, 2]
>>> b
[1, 2]
>>> a is b  # would be False for 2 identical but different list objects
True
>>> id(a) == id(b)
True

id返回对象的内存地址)

而删除与触摸指向的b内容无关:b

>>> a = []
>>> b = a
>>> del b  # a is still untouched and points to a list
>>> b
NameError: name 'b' is not defined
>>> a
[]
于 2014-04-30T10:40:37.600 回答