Clarify how python del works for lists and slices

2020-04-17 04:27发布

问题:

Reading the docs:

del: Deletion of a target list recursively deletes each target, from left to right.

Can you clarify why this code works as it works?

a = [1,2,3]
c = a[:]

del c
print a
del a[:]
print a

This prints:

[1, 2, 3]

[]

if a slice is a new list which points to same elements of the original list, then why deletion of variable assignment of a slice does not make a empty and why deletion of unreferenced slice removes elements of a?

UPD

# -*- coding: utf-8 -*-

a = [1,2,3]
c = a[:]

def list_info(lst):
    print "list id: {}".format(id(lst))
    print "list of item ids:"
    for item in lst:
        print "id: {}; value: {}".format(id(item), item)
    print ""

list_info(a)
list_info(c)
list_info(a[:])

Prints:

list id: 26945296
list of item ids:
id: 23753600; value: 1
id: 23753588; value: 2
id: 23753576; value: 3

list id: 26920560
list of item ids:
id: 23753600; value: 1
id: 23753588; value: 2
id: 23753576; value: 3

list id: 26946136
list of item ids:
id: 23753600; value: 1
id: 23753588; value: 2
id: 23753576; value: 3

As you can see, all list items are actually same objects.

回答1:

Here’s what you’re doing:

a = [1,2,3]

Create new list object. Create name a pointing to it.

c = a[:]

Create copy of list object. Create name c pointing to it.

del c

Delete name c. The object it used to point to is now garbage and will be collected eventually. This has no effect on the first object.

print a

Print what a points to, the first object.

del a[:]

Delete all elements of the object that a points to. It is now an empty list.

print a

Print the empty list.

So, what’s the difference between these lines?

del c
del a[:]

The first line removes a name from the namespace. The second line removes elements from an object.

Edit: I see, you’re not clear on why they act that way. From Python Language Reference, Section 6.5:

Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name occurs in a `global` statement in the same code block. If the name is unbound, a `NameError` exception will be raised.

That’s what happens when you run del c.

Deletion of attribute references, subscriptions and slicings is passed to the primary object involved; deletion of a slicing is in general equivalent to assignment of an empty slice of the right type (but even this is determined by the sliced object).

That’s what happens when you run del a[:].



回答2:

From the doc:

list.clear() Remove all items from the list. Equivalent to del a[:].

del a[:] equals a.clear()

You can try to print id(a) and id(c),they're different objects.