When you do del a[:]
then it looks for the variable a
(including outer contexts) and then performs del found_a[:]
on it.
But when you use a = []
it creates a name a
in the current context and assigns an empty list to it. When the function exits the variable a
from the function is not "accessible" anymore (destroyed).
So in short the first works because you change the a
from an outer context, the second does not work because you don't modify the a
from the outer context, you just create a new a
name and temporarily (for the duration of the function) assigns an empty list to it.
There's a difference between del a[:]
and a = []
Note that these actually do something different which becomes apparent if you have additional references (aliases) to the original list. (as noted by @juanpa.arrivillaga in the comments)
del list[:]
deletes all elements in the list but doesn't create a new list, so the aliases are updated as well:
>>> list_1 = [1,2,3]
>>> alias_1 = list_1
>>> del alist_1[:]
>>> list_1
[]
>>> alias_1
[]
However a = []
creates a new list and assigns that to a
:
>>> list_2 = [1,2,3]
>>> alias_2 = list_2
>>> list_2 = []
>>> list_2
[]
>>> alias_2
[1, 2, 3]
If you want a more extensive discussion about names and references in Python I can highly recommend Ned Batchelders blog post on "Facts and myths about Python names and values".
A better solution?
In most cases where you have multiple variables that belong together I would use a class for them. Then instead of reset
you could simply create a new instance and work on that:
class FourLists:
def __init__(self):
self.a = []
self.b = []
self.c = []
self.d = []
Then you can create a new instance and work with the attributes of that instance:
>>> state = FourLists()
>>> state.a
[]
>>> state.b.append(10)
>>> state.b.extend([1,2,3])
>>> state.b
[10, 1, 2, 3]
Then if you want to reset the state you could simply create a new instance:
>>> new_state = FourLists()
>>> new_state.b
[]