0

I want to generate a square-like text structure in Python using nested lists. An array in which I could modify specific elements at specific indexes with a function like:

def locate(self, x, y):
    return self.array[x][y]

The problem is that as I try to modify an element using multilevel list indexing, many elements are modified as well. Here's my code:

length = 5

tip_row = list('+' * length)
mid_row = list('+' + ' '*(length-2) + '+')

array = [mid_row for _ in range(length-2)]
array.insert(0, tip_row)
array.append(tip_row)

array[3][3] = 'o'

for row in array:
    print(' '.join(row))

I expected the output to be:

+ + + + +
+       +
+   o   +
+       +
+ + + + +

But the actual output is:

+ + + + +
+   o   +
+   o   +
+   o   +
+ + + + +

Apparently, I cannot refer to a specific list in the array. Why is this happening? How can I achieve the expected output?

Paulo Schreiner
  • 109
  • 1
  • 2
  • 9
  • You only have one ***o***, meaning you have 2 types of mid rows. But anyway, How would it look like for an even number (e.g. `length = 4`)? – CristiFati Sep 03 '19 at 15:54
  • take a look at [the python data model](https://docs.python.org/3/reference/datamodel.html#emulating-container-types), and you can use `__getitem__` instead of locate. For the reason why all 3 middle rows are changed, you can check out [this talk](https://rhodesmill.org/brandon/talks/#plummeting-cliff) which explains what variable names and references are. in short: `array = [mid_row for _ in range(length-2)]` copied the reference to `mid_row` 3 times, so all the middle rows point tot the same object – Maarten Fabré Sep 03 '19 at 16:04
  • @MaartenFabré Thanks, your comment solved the problem. Instead of `array = [mid_row for _ in range(length-2)]`, I used `array = [list('+' + ' '*(length-2) + '+') for _ in range(length-2)]`. Same for `tip_row`. Works perfectly! – Paulo Schreiner Sep 03 '19 at 16:55
  • For your edit, the duplicates are right. The problem is when you insert `mid_row` into your array, it only adds a pointer to the values of `mid_row` into your array. So your array is: `[ tip_row, mid_row, mid_row, mid_row, tip_row ]`. When you change `array[3][3]` it changes the 4th element in `mid_row`. So it changes them all! Read on copy vs deep copy. You want to copy the values, not just add a pointer to `mid_row`. – Nic3500 Sep 03 '19 at 16:55
  • Yes, now I get it. I'll remove the edit. Thanks and sorry for not realizing that before. – Paulo Schreiner Sep 03 '19 at 16:58

0 Answers0