简体   繁体   中英

Distinguishing Nested Dict Assignment from List Value Access in a Python Dictionary

I have the dictionary ``body'' of body parts and their corresponding bounding boxes of the form (xmin, ymin, xmax, ymax):

body = {'lHand': [872, 1075, 920, 1194], 'lfoot': [831, 1665, 928, 1777], 
        'rfoot': [676, 1624, 741, 1743], 'rKnee': [657, 1313, 726, 1372], 
        'Lshoul': [809, 678, 885, 740], 'face': [698, 494, 816, 652], 
        'Lknee': [797, 1323, 862, 1395], 'rShoul': [608, 674, 690, 737], 
        'rHand': [563, 1074, 620, 1184], 'hips': [641, 977, 848, 1019]}

and I want to replace each list-value in this dictionary with a nested dictionary where the list elements of each key are themselves labelled: as xmin, ymin, xmax, and ymax, respectively. The goal would be something like

body['part']['coordinate'] = value

like

body['face']['xmin'] = 698

To this end, I've written the following:

for (part, bounding_box) in body.items():
    for (coordinate, value) in zip(['xmin', 'ymin', 'xmax', 'ymax'], bounding_box):
        # the (non-functional) assignment 
        body[part][coordinate] = value
    body[part]['center'] = center(part)
    # joints are centers of body parts
    joint[part] = body[part]['center']

The error I get,

File "body.py", line 110, in <module>
    body[part][coordinate] = value
TypeError: list indices must be integers, not str

makes me think that Python is reading my attempt at creating a nested dictionary element as an attempt to access one of the members of the list associated with key 'part'.

How do I distinguish between these two operations?

Thanks!

Yes, the problem with your approach is that:

body[part][coordinate] = value

body[part] returns the list, and then you try to index the list with the string coordinate , and that fails.

You can just use a dictionary comprehension:

>>> labels = ['xmin', 'ymin', 'xmax', 'ymax']
>>> new_body = {k:dict(zip(labels, v)) for k,v in body.items()}
>>> pprint(new_body)
{'Lknee': {'xmax': 862, 'xmin': 797, 'ymax': 1395, 'ymin': 1323},
 'Lshoul': {'xmax': 885, 'xmin': 809, 'ymax': 740, 'ymin': 678},
 'face': {'xmax': 816, 'xmin': 698, 'ymax': 652, 'ymin': 494},
 'hips': {'xmax': 848, 'xmin': 641, 'ymax': 1019, 'ymin': 977},
 'lHand': {'xmax': 920, 'xmin': 872, 'ymax': 1194, 'ymin': 1075},
 'lfoot': {'xmax': 928, 'xmin': 831, 'ymax': 1777, 'ymin': 1665},
 'rHand': {'xmax': 620, 'xmin': 563, 'ymax': 1184, 'ymin': 1074},
 'rKnee': {'xmax': 726, 'xmin': 657, 'ymax': 1372, 'ymin': 1313},
 'rShoul': {'xmax': 690, 'xmin': 608, 'ymax': 737, 'ymin': 674},
 'rfoot': {'xmax': 741, 'xmin': 676, 'ymax': 1743, 'ymin': 1624}}
>>>

As you wanted:

>>> new_body['face']['xmin']
698
>>>

Of course, the comprehension construct can be replaced by a for-loop:

>>> new_body = {}
>>> for k, v in body.items():
...     new_body[k] = dict(zip(labels, v))
...
>>> pprint(new_body)
{'Lknee': {'xmax': 862, 'xmin': 797, 'ymax': 1395, 'ymin': 1323},
 'Lshoul': {'xmax': 885, 'xmin': 809, 'ymax': 740, 'ymin': 678},
 'face': {'xmax': 816, 'xmin': 698, 'ymax': 652, 'ymin': 494},
 'hips': {'xmax': 848, 'xmin': 641, 'ymax': 1019, 'ymin': 977},
 'lHand': {'xmax': 920, 'xmin': 872, 'ymax': 1194, 'ymin': 1075},
 'lfoot': {'xmax': 928, 'xmin': 831, 'ymax': 1777, 'ymin': 1665},
 'rHand': {'xmax': 620, 'xmin': 563, 'ymax': 1184, 'ymin': 1074},
 'rKnee': {'xmax': 726, 'xmin': 657, 'ymax': 1372, 'ymin': 1313},
 'rShoul': {'xmax': 690, 'xmin': 608, 'ymax': 737, 'ymin': 674},
 'rfoot': {'xmax': 741, 'xmin': 676, 'ymax': 1743, 'ymin': 1624}}
>>>

I think, by reading your code, you were attempting to do it "the long way", something like this:

>>> new_body = {}
>>> for k, v in body.items():
...     new_body[k] = {}
...     for coordinate, value in zip(labels, v):
...         new_body[k][coordinate] = value
...
>>> pprint(new_body)
{'Lknee': {'xmax': 862, 'xmin': 797, 'ymax': 1395, 'ymin': 1323},
 'Lshoul': {'xmax': 885, 'xmin': 809, 'ymax': 740, 'ymin': 678},
 'face': {'xmax': 816, 'xmin': 698, 'ymax': 652, 'ymin': 494},
 'hips': {'xmax': 848, 'xmin': 641, 'ymax': 1019, 'ymin': 977},
 'lHand': {'xmax': 920, 'xmin': 872, 'ymax': 1194, 'ymin': 1075},
 'lfoot': {'xmax': 928, 'xmin': 831, 'ymax': 1777, 'ymin': 1665},
 'rHand': {'xmax': 620, 'xmin': 563, 'ymax': 1184, 'ymin': 1074},
 'rKnee': {'xmax': 726, 'xmin': 657, 'ymax': 1372, 'ymin': 1313},
 'rShoul': {'xmax': 690, 'xmin': 608, 'ymax': 737, 'ymin': 674},
 'rfoot': {'xmax': 741, 'xmin': 676, 'ymax': 1743, 'ymin': 1624}}
>>>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM