using zip() and dictionaries

S

Sneaky Wombat

I'm really confused by what is happening here. If I use zip(), I
can't update individual dictionary elements like I usually do. It
updates all of the dictionary elements. It's hard to explain, so here
is some output from an interactive session:

In [52]: header=['a','b','c','d']
In [53]: columnMap={}
In [54]: for (k,v) in zip(header,[[]]*len(header)):
....: #print "%s,%s"%(k,v)
....: columnMap[k] = v
....:
In [55]: columnMap
Out[55]: {'a': [], 'b': [], 'c': [], 'd': []}
In [56]: columnMap['a'].append('something')
In [57]: columnMap
Out[57]:
{'a': ['something'],
'b': ['something'],
'c': ['something'],
'd': ['something']}

Why does ['something'] get attached to all columnMap elements instead
of just element 'a'?


In [58]: columnMap={'a': [], 'b': [], 'c': [], 'd': []}
In [59]: columnMap['a'].append('something')
In [60]: columnMap
Out[60]: {'a': ['something'], 'b': [], 'c': [], 'd': []}

creating the dictionary without using zip, it works as normal.
 
S

Sneaky Wombat

quick update,

#change this line:
for (k,v) in zip(header,[[]]*len(header)):
#to this line:
for (k,v) in zip(header,[[],[],[],[]]):

and it works as expected. Something about the [[]]*len(header) is
causing the weird behavior. I'm probably using it wrong, but if
anyone can explain why that would happen, i'd appreciate it. My guess
is that it's iterating through the the whole dictionary because of the
value on the right in zip().
 
S

Sneaky Wombat

quick update,

#change this line:
for (k,v) in zip(header,[[]]*len(header)):
#to this line:
for (k,v) in zip(header,[[],[],[],[]]):

and it works as expected. Something about the [[]]*len(header) is
causing the weird behavior. I'm probably using it wrong, but if
anyone can explain why that would happen, i'd appreciate it. My guess
is that it's iterating through the the whole dictionary because of the
value on the right in zip().
 
C

Chris Rebert

I'm really confused by what is happening here.  If I use zip(), I
can't update individual dictionary elements like I usually do.  It
updates all of the dictionary elements.  It's hard to explain, so here
is some output from an interactive session:

In [52]: header=['a','b','c','d']
In [53]: columnMap={}
In [54]: for (k,v) in zip(header,[[]]*len(header)):
   ....:     #print "%s,%s"%(k,v)
   ....:     columnMap[k] = v
   ....:
In [55]: columnMap
Out[55]: {'a': [], 'b': [], 'c': [], 'd': []}
In [56]: columnMap['a'].append('something')
In [57]: columnMap
Out[57]:
{'a': ['something'],
 'b': ['something'],
 'c': ['something'],
 'd': ['something']}

Why does ['something'] get attached to all columnMap elements instead
of just element 'a'?

In [58]: columnMap={'a': [], 'b': [], 'c': [], 'd': []}
In [59]: columnMap['a'].append('something')
In [60]: columnMap
Out[60]: {'a': ['something'], 'b': [], 'c': [], 'd': []}

creating the dictionary without using zip, it works as normal.

quick update,

#change this line:
for (k,v) in zip(header,[[]]*len(header)):
#to this line:
for (k,v) in zip(header,[[],[],[],[]]):

and it works as expected. Something about the [[]]*len(header) is
causing the weird behavior. I'm probably using it wrong, but if
anyone can explain why that would happen, i'd appreciate it. My guess
is that it's iterating through the the whole dictionary because of the
value on the right in zip().

Read http://www.python.org/doc/faq/programming/#how-do-i-create-a-multidimensional-list
Basically, the multiplication doesn't create new sub-lists, it just
copies references to the one original empty sublist.

Cheers,
Chris
 
S

Sneaky Wombat

Thanks! That certainly explains it. This works as expected.

columnMap={}
for (k,v) in zip(header,[[] for i in range(len(header))]):
#print "%s,%s"%(k,v)
columnMap[k] = v

columnMap['a'].append('test')


(sorry about the double post, accidental browser refresh)

I'm really confused by what is happening here.  If I use zip(), I
can't update individual dictionary elements like I usually do.  It
updates all of the dictionary elements.  It's hard to explain, so here
is some output from an interactive session:
In [52]: header=['a','b','c','d']
In [53]: columnMap={}
In [54]: for (k,v) in zip(header,[[]]*len(header)):
   ....:     #print "%s,%s"%(k,v)
   ....:     columnMap[k] = v
   ....:
In [55]: columnMap
Out[55]: {'a': [], 'b': [], 'c': [], 'd': []}
In [56]: columnMap['a'].append('something')
In [57]: columnMap
Out[57]:
{'a': ['something'],
 'b': ['something'],
 'c': ['something'],
 'd': ['something']}
Why does ['something'] get attached to all columnMap elements instead
of just element 'a'?
In [58]: columnMap={'a': [], 'b': [], 'c': [], 'd': []}
In [59]: columnMap['a'].append('something')
In [60]: columnMap
Out[60]: {'a': ['something'], 'b': [], 'c': [], 'd': []}
creating the dictionary without using zip, it works as normal.
quick update,
#change this line:
for (k,v) in zip(header,[[]]*len(header)):
#to this line:
for (k,v) in zip(header,[[],[],[],[]]):
and it works as expected.  Something about the [[]]*len(header) is
causing the weird behavior.  I'm probably using it wrong, but if
anyone can explain why that would happen, i'd appreciate it.  My guess
is that it's iterating through the the whole dictionary because of the
value on the right in zip().

Readhttp://www.python.org/doc/faq/programming/#how-do-i-create-a-multidim....
Basically, the multiplication doesn't create new sub-lists, it just
copies references to the one original empty sublist.

Cheers,
Chris
--http://blog.rebertia.com
 
A

Arnaud Delobelle

Sneaky Wombat said:
I'm really confused by what is happening here. If I use zip(), I
can't update individual dictionary elements like I usually do. It
updates all of the dictionary elements. It's hard to explain, so here
is some output from an interactive session:

In [52]: header=['a','b','c','d']
In [53]: columnMap={}
In [54]: for (k,v) in zip(header,[[]]*len(header)):
....: #print "%s,%s"%(k,v)
....: columnMap[k] = v
....:
In [55]: columnMap
Out[55]: {'a': [], 'b': [], 'c': [], 'd': []}
In [56]: columnMap['a'].append('something')
In [57]: columnMap
Out[57]:
{'a': ['something'],
'b': ['something'],
'c': ['something'],
'd': ['something']}

Why does ['something'] get attached to all columnMap elements instead
of just element 'a'?


In [58]: columnMap={'a': [], 'b': [], 'c': [], 'd': []}
In [59]: columnMap['a'].append('something')
In [60]: columnMap
Out[60]: {'a': ['something'], 'b': [], 'c': [], 'd': []}

creating the dictionary without using zip, it works as normal.

It's a FAQ:

http://www.python.org/doc/faq/programming/#how-do-i-create-a-multidimensional-list
 
S

Simon Forman

quick update,

#change this line:
for (k,v) in zip(header,[[]]*len(header)):
#to this line:
for (k,v) in zip(header,[[],[],[],[]]):

and it works as expected.  Something about the [[]]*len(header) is
causing the weird behavior.  I'm probably using it wrong, but if
anyone can explain why that would happen, i'd appreciate it.  My guess
is that it's iterating through the the whole dictionary because of the
value on the right in zip().

I'm really confused by what is happening here.  If I use zip(), I
can't update individual dictionary elements like I usually do.  It
updates all of the dictionary elements.  It's hard to explain, so here
is some output from an interactive session:
In [52]: header=['a','b','c','d']
In [53]: columnMap={}
In [54]: for (k,v) in zip(header,[[]]*len(header)):
   ....:     #print "%s,%s"%(k,v)
   ....:     columnMap[k] = v
   ....:
In [55]: columnMap
Out[55]: {'a': [], 'b': [], 'c': [], 'd': []}
In [56]: columnMap['a'].append('something')
In [57]: columnMap
Out[57]:
{'a': ['something'],
 'b': ['something'],
 'c': ['something'],
 'd': ['something']}
Why does ['something'] get attached to all columnMap elements instead
of just element 'a'?
In [58]: columnMap={'a': [], 'b': [], 'c': [], 'd': []}
In [59]: columnMap['a'].append('something')
In [60]: columnMap
Out[60]: {'a': ['something'], 'b': [], 'c': [], 'd': []}
creating the dictionary without using zip, it works as normal.

You figured out your original question, I just wanted to point out
that your code as posted is less efficient than it could be.
Rather than creating a list of empty lists to feed to zip() you could
just assign a new empty list to columnMap in your loop body, like so:

In [54]: for k in header:
....: columnMap[k] = []

That avoids creating a list of lists just to pass to zip() the call to
zip() too.
~S
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top