building lists of dictionaries
Tim Chase
python.list at tim.thechases.com
Sun Jul 23 11:57:56 EDT 2006
> parinfo = [{'value':0., 'fixed':0, 'limited':[0,0],
'limits':[0.,0.]}]*6
> parinfo[0]['fixed'] = 1
> parinfo[4]['limited'][0] = 1
> parinfo[4]['limits'][0] = 50.
>
> The first line builds a list of six dictionaries with
> initialised keys. I expected that the last three lines
> would only affect the corresponding keys of the
> corresponding dictionnary and that I would end up with a
> fully initialised list where only the 'fixed' key of the
> first dict would be 1, and the first values of limited and
> limits for dict number 4 would be 1 and 50.
> respectively....
>
> This is not so! I end up with all dictionaries being
> identical and having their 'fixed' key set to 1, and
> limited[0]==1 and limits[0]==50.
> I do not understand this behaviour...
The *6 creates multiple references to the same dictionary.
Thus, when you update the dictionary through one
reference/name (parinfo[0]), the things that the other
entries (parinfo[1:5]) reference that changed dictionary.
You're likely looking for something like
parinfo = [{'value':0., 'fixed':0, 'limited':[0,0],
'limits':[0.,0.]}]
for i in xrange(1,6): parinfo.append(parinfo[0].copy())
or something like
parinfo = [{'value':0., 'fixed':0, 'limited':[0,0],
'limits':[0.,0.]}.copy() for i in xrange(0,6)]
However, this will still reference internal lists that have
been referenced multiple times, such that
>>> parinfo[5]['limited']
[0, 0]
>>> parinfo[4]['limited'][0] = 2
>>> parinfo[5]['limited']
[2, 0]
Thus, you'd also want to change it to be something like
parinfo = [
{'value':0.,
'fixed':0,
'limited':[0, 0][:],
'limits':[0., 0.][:]
}.copy() for i in xrange(0, 6)]
where the slice operator is used to build a copy of the list
for each element as well (rather than keeping a reference to
the same list for each dictionary).
Hopefully this makes some sense, and helps get you on your
way.
-tkc
More information about the Python-list
mailing list