-2

I am trying to create a 12x12 matrix in Python. I set all locations to "High" then I try to set one particular location to "Low". In the print commands both are "Low" when I wanted the first one to be "Low" and I hoped the second was still "High" because it wasn't changed (I thought). What am I doing wrong?

HourlyUsageBlock = ["High" for x in range(12)]
WorkDayUsageBlock = [HourlyUsageBlock for x in range(12)]
Hour = 2
MinBlock = 6
WorkDayUsageBlock [MinBlock][Hour] = "Low"
print (WorkDayUsageBlock[6][2])
print (WorkDayUsageBlock[10][2])
martineau
  • 119,623
  • 25
  • 170
  • 301
Derek049
  • 3
  • 1
  • Possible duplicate of [How to initialize a two-dimensional array in Python?](http://stackoverflow.com/questions/2397141/how-to-initialize-a-two-dimensional-array-in-python) – pvg Apr 22 '17 at 15:18
  • 1
    What you're doing wrong is you're putting a reference to the same thing (`HourlyUsageBlock`) in `WorkDayUsageBlock`. Your comprehension doesn't make a _copy_ , it just points to it. `WorkDayUsageBlock` is a list of things that point to the same exact `HourlyUsageBlock`. – pvg Apr 22 '17 at 15:20
  • @pvg: No, not a duplicate of that question IMO. – martineau Apr 22 '17 at 15:26
  • Thanks, I replaced the first two lines with: WorkDayUsageBlock = [["High" for x in range(12)] for y in range(12)] and it works – Derek049 Apr 22 '17 at 15:27
  • Off-topic: If you're going to be writing much Python code, I suggest you read and follow [PEP 8 - Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/). It will make your code more readable to others (and yourself, eventually). – martineau Apr 22 '17 at 15:29
  • @martineau the problem gets mentioned but maybe not. It's definitely a dupe though, although it's one of those superdupes where it's hard to find the most canonical answer. – pvg Apr 22 '17 at 15:33
  • @pvg: Never heard of a "superdup" before. The accepted and highly up-voted answer to the linked question basically just describes [list comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions), which the OP obviously knows something about since their code uses them. However the answer's pretty vague about how exactly to apply them to a two-dimensional list, much less about how to avoid the problem mentioned in this question. – martineau Apr 22 '17 at 15:53
  • @martineau you haven't heard it because I made it up! The fundamental issue - not quite getting a handle on reference vs value is very, very common, you see python questions like that daily. There's got to be a canonical SO answer for that just like, say, the java tag has a 'Why am I getting an NPE and how do I fix it' answer. – pvg Apr 22 '17 at 16:07

2 Answers2

0
>>> print (WorkDayUsageBlock)
[['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High'], ['High', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High', 'High']]

you could see every 3rd element of every row is 'Low' because comprehension just make use of same HourlyUsageBlock. So when you change the value of 3rd element, it gets reflected in every row as comprehension doesn't make copy of HourlyUsageBlock.

Ajay Singh
  • 1,251
  • 14
  • 17
0

When you initialize WorkDayUsageBlock You basically put the same HourlyUsageBlock in every position. Because all elements in the WorkDay are the same list, changing one will change all.

Try this solution:

WorkDayUsageBlock = [["high" for x in range(12)] for y in range(12)]

Or, you can use lst.copy():

WorkDayUsageBlock = [HourlyUsageBlock.copy() for x in range(12)]

I suggest you to read about mutable and imutable objects in Python.

Alon Alexander
  • 135
  • 3
  • 10
  • In Python 2, `list` objects like `HourlyUsageBlock` don't have a `copy()` method and it wasn't added until Python 3.3. However in both Python 2 & 3, one could obtain a copy of the `list` instance by using `[HourlyUsageBlock[:] for _ in range(12)]`. – martineau Apr 22 '17 at 16:03