简体   繁体   中英

In Python, why my variable StartingU get updated when I only update the variable AverageU in my for loops? What is wrong with the code?

The purpose is to calculate the average value (AverageU) from a starting array (StartingU)

import numpy as np

AverageU=np.zeros((3,3))
StartingU=np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

size=2
stride=1
m, n = StartingU.shape

print("Before averaging:")
print("AverageU=", AverageU)
print("StartingU=", StartingU)

AverageU = StartingU

The for loops that calculate the average values for AverageU

for i in range(0, m - size + 1, stride):
    for j in range(0, n - size + 1, stride):
        avg = np.sum(np.sum(AverageU[i:i + size, j:j + size])) / (size * size)
        for ii in range(i, i + size):
            for jj in range(j, j + size):
                AverageU[ii, jj] = avg
                #print("In for loop, StartingU=", StartingU)
     
print("After averaging:")
print("AverageU=", AverageU)
print("StartingU=", StartingU)

Output:

Before averaging:
AverageU= [[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]
StartingU= [[1 2 3]
 [4 5 6]
 [7 8 9]]
After averaging:
AverageU= [[3 3 3]
 [5 5 5]
 [5 5 5]]
StartingU= [[3 3 3]
 [5 5 5]
 [5 5 5]]

The problem is why StartingU gets updated? It should be unchanged

StartingU=np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

AverageU changed since this code, not after for loop.

print("Before averaging:")
print("AverageU=", AverageU)
print("StartingU=", StartingU)

AverageU = StartingU  # since here, AverageU variable changed

print("AverageU=", AverageU)
print("StartingU=", StartingU)  # please check here again.

AverageU and StartingU are the same instances. You can check it with is function.

StartingU = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
AverageU = StartingU
print(StartingU is AverageU)  # True

You should make a new instance as the comment said.

StartingU = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

AverageU_new1 = StartingU[:]
AverageU_new2 = StartingU.copy()
print(StartingU is AverageU_new2)  # False
print(StartingU is AverageU_new1)  # False

AverageU = StartingU This code just makes another reference to the same object with a new name and this indicates the same memory. You can check the memory address of the variable with function id

You can compare like this.

copy_1 = StartingU
copy_2 = StartingU[:]
copy_3 = StartingU.copy()
print(id(StartingU), id(copy_1), id(copy_2), id(copy_3))

Notice

Copy with the colon is actually a shallow copy, it copies only the reference of the nested list.

Thank you Lazyer for your suggestions. By trying AverageU=StartingU.copy() , I have got the solution. Yes, you are right.

Actually, the below simplified code shows the right answer.

import numpy as np

A=np.array([[1, 2, 3], [4, 5, 6],[7, 8, 9]])

# B=A[:] this one still gets A updated
B=A.copy()
for i in range(0,3):
    for j in range(0,3):
        B[i,j]=2

print("A=",A)

print("B=", B)

The output:

A= [[1 2 3]
    [4 5 6]
    [7 8 9]]
B= [[2 2 2]
    [2 2 2]
    [2 2 2]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM