Question

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
[]
>>> 
Was it helpful?

Solution

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.

OTHER TIPS

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.]

The append method works against the actual object, while del works against the reference i.e. variable name.

(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
[]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top