-1

I need to create a list of dates that contains IDs and one that does not contain IDs. The for loop is acting on without_ids so why do the two print with_ids statement yield different results (column 1 is missing)?

import datetime
with_ids = [[u'ID 1', datetime.datetime(2014, 12, 9, 0, 0), datetime.datetime(2015, 2, 17, 0, 0), datetime.datetime(2015, 3, 4, 0, 0), datetime.datetime(2015, 3, 13, 0, 0)], [u'ID 2', datetime.datetime(2014, 12, 9, 0, 0), datetime.datetime(2015, 2, 17, 0, 0), datetime.datetime(2015, 3, 4, 0, 0), datetime.datetime(2015, 3, 13, 0, 0)]]
print with_ids
without_ids = with_ids
for x in without_ids:
    del x[0]
print "\n"
print with_ids

Output:

[[u'ID 1', datetime.datetime(2014, 12, 9, 0, 0), datetime.datetime(2015, 2, 17, 0, 0), datetime.datetime(2015, 3, 4, 0, 0), datetime.datetime(2015, 3, 13, 0, 0)], [u'ID 2', datetime.datetime(2014, 12, 9, 0, 0), datetime.datetime(2015, 2, 17, 0, 0), datetime.datetime(2015, 3, 4, 0, 0), datetime.datetime(2015, 3, 13, 0, 0)]]


[[datetime.datetime(2014, 12, 9, 0, 0), datetime.datetime(2015, 2, 17, 0, 0), datetime.datetime(2015, 3, 4, 0, 0), datetime.datetime(2015, 3, 13, 0, 0)], [datetime.datetime(2014, 12, 9, 0, 0), datetime.datetime(2015, 2, 17, 0, 0), datetime.datetime(2015, 3, 4, 0, 0), datetime.datetime(2015, 3, 13, 0, 0)]]
user2242044
  • 8,803
  • 25
  • 97
  • 164

2 Answers2

1
without_ids = with_ids

Since with_ids references a list, without_ids will no reference the same list. Thus, when you delete items from without_ids, you are deleting the items from the underlying list object, which is the same list that with_ids is still referencing. So all your changes to the same object appear for all variables referencing the same object.

You have to create a copy of the list instead of copying the reference. Usually, you would do it like this:

without_ids = with_ids[:]

However, this will only copy the outer list, making it a shallow copy. Since your list contains list of lists, you would need a deep copy. And at that point, it becomes a bit tedious.

So instead of creating a copy, you could create a new list instead that just contains the elements you want to keep:

without_ids = [elem[1:] for elem in with_ids]

This is a list comprehension that will iterate over all elements in with_ids and just select all of that sub-lists element except the first (elem[1:] means start at the first index and take everything afterwards), and make a new list from those.

poke
  • 369,085
  • 72
  • 557
  • 602
1

In the statement

without_ids = with_ids

you are making without_ids refer to the same object as with_ids (this is known as aliasing).

What can you do? You can make a deep copy (a simple copy with_ids[:] won't work, because it is a nested list):

import copy
without_ids = copy.deepcopy(with_ids)
Christian Tapia
  • 33,620
  • 7
  • 56
  • 73