0

I'm trying to keep track of something with 5 categories and 10 subcategories each. Each item is described with a 0 or a 1. I decided to make a list of lists in the following format:

[[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]...]

When trying to assign a value to only one of these sub-lists, the code assign it to all the sub-lists.

This is a snippet of the code:

categories=['a','b','c','d','e','f']

status=[]
zeros=[0,0,0,0,0,0,0,0,0,0]
for i in categories:
    status.append(zeros)

print(status)

category=0
subcategory=1

status[category][subcategory] = 2

print(status)

result:

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
[[0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0, 0, 0, 0]]

I want the program to only edit one list at a time but instead if edits all the subcategories. What am I doing wrong here?

martineau
  • 119,623
  • 25
  • 170
  • 301
Gio
  • 1

1 Answers1

1

You've appended the same list (originally named zeroes) to your status list multiple times. That is, it has n references to the same underlying object, so when you mutate it you see the mutations in each of those references.

You want to make an independent copy of zeroes each time you append it, or build a new object each time. Because it contains only integer values a shallow copy is fine, you can get one of those with the slice operator [:]:

for i in categories:
    status.append(zeros[:])

If your list might contain references to mutable objects, you'd want to use the copy built in module instead of a complete slice. copy.copy() is a shallow copy and therefore equivalent to slicing, so that's an acceptable option here if you prefer it but [:] is the more common Python idiom. copy.deepcopy() would handle mutable types, such as if you wanted to copy status after creating it with independent sublists.

Or you can make a new list of zeroes:

for i in categories:
    status.append([0] * num_subcategories)

Note that that last idiom shallow copies as well, making a list of num_subcategories identical references to the single element of the list. That's fine here, but a common way to get into the situation you were originally in if you use it to expand a list of lists. Don't do this if you're expecting independent lists:

list_of_lists = [[]] * n

Also don't do this:

status = [zeroes] * num_categories

I mention this because it's so closely related to your original problem, and a common way to try to set up a two-dimension array.

Peter DeGlopper
  • 36,326
  • 7
  • 90
  • 83
  • Thanks. I used the first method and it solved the issue. I didn't know it was appending the same object. – Gio Mar 01 '21 at 19:57