On Fri, 09 Mar 2007 17:30:09 -0800, kghose wrote:
Hi,
The following code
listoflists = [[]]*2
listoflists[0].append(1)
appends(1) to both listoflists[0] and listoflists[1] (which I did not
expect)
I think you will find the same question raised barely a few hours ago.
Hint:
>>list_of_lists = [[]]*2
id(list_of_lists[0])
-1211466452
>>id(list_of_lists[1])
-1211466452
Notice that both inner lists have the same ID? That tells you that they
are the same list.
Like about what [obj]*2 does. Does it create multiple copies of obj? No it
does not. Python never makes copies of objects unless you explicitly tell
it to.
[] on it's own creates a new empty list, so [[], []] creates a list with
two DIFFERENT empty lists in it. [[]] creates a list with one empty list
in it; *2 makes a second reference (not a copy!) of that empty list.
while
listoflists = [[]]*2
listoflists[0] = [1]
listoflists[0].append(2)
works as expected.i.e. only listoflists[0] gets 2 appended to it and
any further operations work as expected.
>>list_of_lists[0] = [] # creates a new empty list
id(list_of_lists[0])
-1211466228
>>id(list_of_lists[1]) # same ID as before
-1211466452
You know, now that Python has a warnings module, it would be really good
if list-of-lists*int raised a warning. Does anyone know if that's feasible
or possible? It needn't catch every imaginable Gotcha, just the common
case. I'm thinking something like this:
# pseudo-code
class list:
def __mul__(self, count):
for item in self:
if isinstance(item, list):
warn("this duplicates references, not copies")
break
...do the rest
--
Steven.