0

can you lease tell me why S[f'{colors[0]}'] is changing after calling this function, and how to fix it.

S = {"1": list(range(0,5)), "2": list(range(20,25)), "3": list(range(10,15))}
colors = [1, 2 ,3]

def count_bycolor(colors):
    countries_bycolor = S[f'{colors[0]}']
    for i in range(1, len(colors)):
        countries_bycolor.extend(S[f'{colors[i]}'])
    return countries_bycolor

count_bycolor(colors)
len(S[f'{colors[0]}'])
count_bycolor(colors)
len(S[f'{colors[0]}'])

Thank for your help, and happy holidays!

  • It is changing because you change it in the line `countries_bycolor.extend(S[f'{colors[i]}'])`. In order to help you, you will have to give more details on what you are trying to achieve here. What is your expected behaviour? – Tomerikoo Dec 20 '19 at 15:54
  • `countries_bycolor` is literally the list in `S` after `countries_bycolor = S[f'{colors[0]}']`; it's not a copy. If you want it to change independently, you need to [make a copy of it](https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list). – Carcigenicate Dec 20 '19 at 15:55
  • Clear, thanks and happy holidays. – Anas BELFADIL Dec 20 '19 at 15:59

1 Answers1

2

You are performing operations on a list in a dict. Both of these are mutable objects and due to python being passed by reference pass-by-object-reference that has this consequence of changing your "original" object (it's the same object).

This means that you need to make copies of those objects if you want to operate on them without changing the original.

Based on your question it could be as simple as one line change:

import copy

def count_bycolor(colors):
    countries_bycolor = copy.copy(S[f'{colors[0]}'])
    for i in range(1, len(colors)):
        countries_bycolor.extend(S[f'{colors[i]}'])
    return countries_bycolor

count_bycolor(colors)

>>> [0, 1, 2, 3, 4, 20, 21, 22, 23, 24, 10, 11, 12, 13, 14]

S

>>> {'1': [0, 1, 2, 3, 4], '2': [20, 21, 22, 23, 24], '3': [10, 11, 12, 13, 14]}
PyPingu
  • 1,697
  • 1
  • 8
  • 21