问题
Why does the following code change both variables:
>>> a = []
>>> b = a
>>> a.append(9)
>>> a
[9]
>>> b
[9]
>>>
But the del
statement does not achieve the same effect?
>>> a = []
>>> b = a
>>> del(a)
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b
[]
>>>
回答1:
When you do:
a = b
What you're doing is assigning the label b
to the same object that the label a
is refering to.
When you do:
a.append(9)
You're adding 9
to the list object pointed to by both a
and b
. It's the same object, so they show the same result.
When you do:
del a
You're deleting the reference to the object, not the object itself. If it's the only reference, then the object will be garbage collected. But in your case, there's another reference - b
- so the object continues to exist.
回答2:
Instead of "variables", think in terms of names and objects.
>>> a = []
This makes an empty list object and binds the name a
to it.
>>> b = a
This simply says that b
is now a new name for the object named by a
. We have
>>> a is b
True
del a
means that we're forgetting the name a
: it is no longer bound to an object.
>>> del a
>>> a
Traceback (most recent call last):
File "<ipython-input-8-60b725f10c9c>", line 1, in <module>
a
NameError: name 'a' is not defined
But that you're no longer calling that list object a
, only b
, doesn't affect the object itself in any way. Objects don't care, or even know about, what names you've given them. [One semi-exception is that if an object no longer has any references, it may -- or may not, no promises -- be garbage-collected.]
回答3:
The append
method works against the actual object, while del
works against the reference i.e. variable name.
回答4:
(I already answered the question in the other question of yours, so I'm going to use it here as well, with slight modifications:)
del
does not delete objects; in fact in Python, it is not even possible to tell the interpreter/VM to remove an object from memory because Python is a garbage collected language (like Java, C#, Ruby, Haskell etc).
Instead, what del
does when called on a variable (as opposed to a dictionary key or list item) like this:
del a
is that it only removes the local (or global) variable not what it points to (every variable in Python holds a pointer/reference to its contents not the content itself). In fact, since locals and globals are stored as a dictionary under the hood (see locals()
and globals()
), del a
is equivalent to:
del locals()['a']
(or del globals()['a']
when applied to a global.)
so if you have:
a = []
b = a
you're making a list, storing a reference to it in a
and then copying that reference into b
without copying/touching the list object itself. Therefore these two calls affect one and the same object:
>>> 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
returns the memory address of an object)
whereas deleting b
is in no way related to touching what b
points to:
>>> a = []
>>> b = a
>>> del b # a is still untouched and points to a list
>>> b
NameError: name 'b' is not defined
>>> a
[]
来源:https://stackoverflow.com/questions/23377478/why-doesnt-del-do-the-same-thing