0

I have a list of three dicts, of which I change values of each dict within a for-loop. Print statements confirm that each loop has altered its corresponding dict (to different values, hence the dicts should not be identical after the for loop). However, once I print the complete list immediately after the for-loop, the list contains identical dicts. My code looks like this:

split_tag = []
    for _ in split_polygon: split_tag.append(tag) # len(split_polygon) is 3
print("Initial tags: " + str(split_tag))
for i, pg in enumerate(split_polygon):
    split_tag[i]["polygon"] = pg
    split_tag[i]["bbox"] = bound_box(pg)
    print("Splitted tag " + str(i) + ": " + str(split_tag[i]))
print("Final tags: " + str(split_tag))

Python 2.7 and Python 3.5 both give the following output:

Initial tags: [{'score': 0, 'polygon': [(1668.0832177531206, 2588.404993065187), (1668.0832177531206, 3662.113730929265), (1175.9667128987517, 3662.113730929265), (1311.0385388560185, 2837.768364063218)], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1175.9667128987517, 2588.404993065187, 492.11650485436894, 1073.7087378640776), 'ref_id': 321745191097315359679355396732871380055L}, {'score': 0, 'polygon': [(1668.0832177531206, 2588.404993065187), (1668.0832177531206, 3662.113730929265), (1175.9667128987517, 3662.113730929265), (1311.0385388560185, 2837.768364063218)], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1175.9667128987517, 2588.404993065187, 492.11650485436894, 1073.7087378640776), 'ref_id': 321745191097315359679355396732871380055L}, {'score': 0, 'polygon': [(1668.0832177531206, 2588.404993065187), (1668.0832177531206, 3662.113730929265), (1175.9667128987517, 3662.113730929265), (1311.0385388560185, 2837.768364063218)], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1175.9667128987517, 2588.404993065187, 492.11650485436894, 1073.7087378640776), 'ref_id': 321745191097315359679355396732871380055L}]
Splitted tag 0: {'score': 0, 'polygon': [[1668, 3662], [1175, 3662], [1247, 3227], [1668, 3191]], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1175, 3191, 493, 471), 'ref_id': 321745191097315359679355396732871380055L}
Splitted tag 1: {'score': 0, 'polygon': [[1409, 3134], [1259, 3155], [1311, 2837], [1344, 2814], [1388, 2933], [1384, 2786], [1430, 2754]], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1259, 2754, 171, 401), 'ref_id': 321745191097315359679355396732871380055L}
Splitted tag 2: {'score': 0, 'polygon': [[1668, 3074], [1486, 2987], [1473, 2724], [1668, 2588]], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1473, 2588, 195, 486), 'ref_id': 321745191097315359679355396732871380055L}
Final tags: [{'score': 0, 'polygon': [[1668, 3074], [1486, 2987], [1473, 2724], [1668, 2588]], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1473, 2588, 195, 486), 'ref_id': 321745191097315359679355396732871380055L}, {'score': 0, 'polygon': [[1668, 3074], [1486, 2987], [1473, 2724], [1668, 2588]], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1473, 2588, 195, 486), 'ref_id': 321745191097315359679355396732871380055L}, {'score': 0, 'polygon': [[1668, 3074], [1486, 2987], [1473, 2724], [1668, 2588]], 'tagname': u'asphalt', 'type': 'MyPolygonItem', 'bbox': (1473, 2588, 195, 486), 'ref_id': 321745191097315359679355396732871380055L}]

Printing each dict separately at the end of each loop shows that they have indeed been mutated; at least, the polygon and bbox values have been. However, printing the whole list at the end shows that the dicts are now suddenly identical, including polygon and bbox.

Does anyone know why and where my list is secretely being mutated? Does the for-loop perhaps work on some kind of local version of split_tag?

For reference, my bound__box() function is as follows:

def bound_box(coordinate_pairs):
    x_min = 999999
    y_min = 999999
    x_max = 0
    y_max = 0

    for pair in coordinate_pairs:
        if pair[0] < x_min: x_min = pair[0]
        if pair[0] > x_max: x_max = pair[0]
        if pair[1] < y_min: y_min = pair[1]
        if pair[1] > y_max: y_max = pair[1]

    return (x_min, y_min, x_max - x_min, y_max - y_min)
  • 1
    fix: `split_tag = [tag for _ in range(len(split_polygon))]`. or even: `split_tag = [tag for _ in split_polygon]`. – hiro protagonist May 06 '19 at 11:27
  • Thanks! But that still yields the same results, unfortunately. I also tried initializing as ```split_tag = [], for _ in split_polygon: split_tag.append(tag)```, which also doesn't work, for both Python 2.7 and 3.5. –  May 06 '19 at 11:34
  • oops! ok, then please fix that in your question and i will reopen the question... (also add `bounding_box` in order to make it a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve)). – hiro protagonist May 06 '19 at 11:36
  • Done, and no problem! I would've sworn that that should have been the solution. –  May 06 '19 at 11:41
  • 2
    `split_tag.append(tag)` in the beginning should be `split_tag.append(deepcopy(tag))`, where deepcopy is a concept, not a specific method – Mad Physicist May 06 '19 at 11:48
  • ah, `tag` is mutable... did not see that at first glance. – hiro protagonist May 06 '19 at 12:10

0 Answers0