2

If you have the following list of lists:

>> A = [[1], [2]]

And then say you assign the 2nd list to the first list by:

>> A[0] = A[1]

You end up with the following:

>> print A
[[2], [2]]

So A[0] and A[1] point to the same list now. If you append an element to the first by:

>> A[0].append(3)

You will get the following:

>> print A
[[2,3], [2,3]]

However, if you try to delete the first list by:

>> del A[0]

Then only one list is removed, as follows:

>> print A
[[1,2]]

Q1.1: Why is the behavior different? One might expect both lists to be removed.

Clearly, if one just wants to make a copy of A[1] then the following works correctly:

>> A = [[1], [2]]
>> A[0] = list(A[1])
>> print A
[[2], [2]]
>> A[0].append(3)
>> print A
[[2,3], [2]]

The problem with this is that its running time is linear with the size of the list to copy, i.e., A[1].

Q1.2: Can one copy a list from another without linear-time copy operation?

TrainedScarab
  • 25
  • 1
  • 5

3 Answers3

1

Q1.1.

You have to differentiate between an object and object identity. Identity is just a logical address to the memory cell of the object. When you are doing A[0] = A[1], you don't actually copy the object, but you get a new identity to the object. After A[0] = A[1], you have two identities A[0] and A[1] to the same object, so when you do A[0].append(...) or A[1].append(.), what is actually being affected is the same object.

Now about lists. Lists in Python don't hold objects. They hold identities of the objects. You can check this by comparing

sys.getsizeof([1]) and sys.getsizeof([1000000000000000000000000000000]),

both will have the same size although 10000000000000000000000000000000 is obviously heavier than 1.

What del does is, it removes an element from the list, which happens to be one of the two identities and not the object, so when you have a list that holds two identities to the same object and del one of them, you still keep the object and the other identity because the object is still referenced.

Q1.2.

If you want to copy, you can just do A[0] = A[1][:], which will assign A[0] to a slice. It should be faster. Check this.

Community
  • 1
  • 1
khajvah
  • 4,889
  • 9
  • 41
  • 63
  • I would say "references" instead of "identities"; I think "references" is the more commonly used terminology? – Vultaire Apr 03 '15 at 06:42
  • @Vultaire It might be but "identity" is used in python's [documentation](https://docs.python.org/3.4/reference/datamodel.html), so I just used "identity" to keep it consistent. – khajvah Apr 03 '15 at 06:43
  • And from @itzmeontv's answer, you can get the identity value by `id(A[0])`. – TrainedScarab Apr 03 '15 at 06:49
  • 1
    @TrainedScarab I might have been wrong about O(1) but it should be faster. I updated the answer. – khajvah Apr 03 '15 at 06:57
  • @khajvah Interesting; I didn't see how the docs used the term. Thanks; I'll keep this in mind in the future. – Vultaire Apr 03 '15 at 14:42
0

del A[0] doesn't means to delete an entry of A[0] element And would be deleted at garbage collection. It just stand for deleting a reference link from A[0] variable to list ([2,3]).

Ankit Sachdeva
  • 179
  • 1
  • 9
0

Q1.1: Why is the behavior different? One might expect both lists to be removed.

del A[0] 

is not deallocating the memory of list [2,3] or nor deleting the list.It just removing tag or referevce A[0] to the list [2,3].

Q1.2: Can one copy a list from another without linear-time copy operation?

A[0] = A[1][:]

For example

A = [[1], [2]]
A[0] = A[1][:]

>>id(A[0]),id(A[1])
(140215217604552, 140215217619208)
itzMEonTV
  • 19,851
  • 4
  • 39
  • 49