Jump to content

Python. I cannot figure out why changing one array is affecting another

Go to solution Solved by Deopwr,
2 minutes ago, aconncep said:

It also looks like the variable k is not being used inside the diffuse() method. Are you meaning to assign that instead of 0?

the variable was used in some other code that was not relevant to the question also i managed to fix the problem by using this:

import copy
gridN = [[copy.copy(cell_obj) for cell_obj in line] for line in grid]

 

So basically I have a main 2d array called grid filled with cell objects and I create a clone of this array called gridN for later use but when I set all of gridN's density to 0 the main grid's density is set to 0 aswell. 

 

class cell:
    x = 0
    y = 0

    den = 0

    velX = 0
    velY = 0

width = 10
height = 10
grid = []


for i in range(width):
    grid.append([])
    for j in range(height):
        grid[i].append(cell())
        grid[i][j].x = i
        grid[i][j].y = j


def diffuse(k,grid):
    gridC = list(grid)
    gridN = list(grid)
    
    for i in range(width):
        gridN.append([])
        for j in range(height):
            gridN[i].append(cell())
            gridN[i][j].den = 0
    print(gridN[0][0].den)
    
grid[0][0].den = 100
diffuse(0.5,grid)

 

Link to comment
Share on other sites

Link to post
Share on other sites

You need an __init__() method inside your cell class. 

 

class cell:
    def __init__(self):
    	self.x = 0
      	self.y = 0
		
      	self.den = 0
		
      	self.velX = 0
      	self.velY = 0

 

Otherwise all instances of Cell share the same values.

Link to comment
Share on other sites

Link to post
Share on other sites

16 minutes ago, aconncep said:

You need an __init__() method inside your cell class. 

 

class cell:
    def __init__(self):
    	self.x = 0
      	self.y = 0
		
      	self.den = 0
		
      	self.velX = 0
      	self.velY = 0

 

Otherwise all instances of Cell share the same values.

I just tried replacing the class with the one you provided but the print still shows zero. I think maybe there is more than one issue.

class cell:
    def __init__(self):
        self.x = 0
        self.y = 0
		
        self.den = 0
		
        self.velX = 0
        self.velY = 0

width = 10
height = 10
grid = []


for i in range(width):
    grid.append([])
    for j in range(height):
        grid[i].append(cell())
        grid[i][j].x = i
        grid[i][j].y = j


def diffuse(k,grid):
    gridN = list(grid)
    
    for i in range(width):
        gridN.append([])
        for j in range(height):
            gridN[i].append(cell())
            gridN[i][j].den = 0
    print(grid[0][0].den)

    
grid[0][0].den = 100
diffuse(0.5,grid)

 

Link to comment
Share on other sites

Link to post
Share on other sites

4 minutes ago, Deopwr said:

I just tried replacing the class with the one you provided but the print still shows zero. I think maybe there is more than one issue.

class cell:
    def __init__(self):
        self.x = 0
        self.y = 0
		
        self.den = 0
		
        self.velX = 0
        self.velY = 0

width = 10
height = 10
grid = []


for i in range(width):
    grid.append([])
    for j in range(height):
        grid[i].append(cell())
        grid[i][j].x = i
        grid[i][j].y = j


def diffuse(k,grid):
    gridN = list(grid)
    
    for i in range(width):
        gridN.append([])
        for j in range(height):
            gridN[i].append(cell())
            gridN[i][j].den = 0
    print(grid[0][0].den)

    
grid[0][0].den = 100
diffuse(0.5,grid)

 

It also looks like the variable k is not being used inside the diffuse() method. Are you meaning to assign that instead of 0?

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, aconncep said:

It also looks like the variable k is not being used inside the diffuse() method. Are you meaning to assign that instead of 0?

the variable was used in some other code that was not relevant to the question also i managed to fix the problem by using this:

import copy
gridN = [[copy.copy(cell_obj) for cell_obj in line] for line in grid]

 

Link to comment
Share on other sites

Link to post
Share on other sites

Append, well, appends values. That means the lists will get new entries at it end. Your first for loop generates your grid with 100 in its top left corner.

for i in range(width):
    grid.append([])
    for j in range(height):
        grid[i].append(cell())
        grid[i][j].x = i
        grid[i][j].y = j
        
grid[0][0].den = 100
for y in grid:
    print([x.den for x in y])
    
    
# Output
[100, 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, 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]

Now what happens in your second for loop is that you add new cells at the end of each row. Not only does your grid become bigger, your loop modifies only the first 1 to width and 1 to height entries of each row. Instead of putting them to 0 I've put them to 3 so we can see what happens:

def diffuse(k,grid):
    gridC = list(grid)
    gridN = list(grid)
    for i in range(width):
        gridN.append([])
        for j in range(height):
            gridN[i].append(cell())
            gridN[i][j].den = 3
    print(gridN[0][0].den)
    
grid[0][0].den = 100
diffuse(0.5,grid)
for y in grid:
    print([x.den for x in y])
    
# Output
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

 

Its first modification will be entry [0, 0] (the value you set to 100), which is thus reset to 0.

Crystal: CPU: i7 7700K | Motherboard: Asus ROG Strix Z270F | RAM: GSkill 16 GB@3200MHz | GPU: Nvidia GTX 1080 Ti FE | Case: Corsair Crystal 570X (black) | PSU: EVGA Supernova G2 1000W | Monitor: Asus VG248QE 24"

Laptop: Dell XPS 13 9370 | CPU: i5 10510U | RAM: 16 GB

Server: CPU: i5 4690k | RAM: 16 GB | Case: Corsair Graphite 760T White | Storage: 19 TB

Link to comment
Share on other sites

Link to post
Share on other sites

14 hours ago, tikker said:

Append, well, appends values. That means the lists will get new entries at it end. Your first for loop generates your grid with 100 in its top left corner.

for i in range(width):
    grid.append([])
    for j in range(height):
        grid[i].append(cell())
        grid[i][j].x = i
        grid[i][j].y = j
        
grid[0][0].den = 100
for y in grid:
    print([x.den for x in y])
    
    
# Output
[100, 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, 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]

Now what happens in your second for loop is that you add new cells at the end of each row. Not only does your grid become bigger, your loop modifies only the first 1 to width and 1 to height entries of each row. Instead of putting them to 0 I've put them to 3 so we can see what happens:

def diffuse(k,grid):
    gridC = list(grid)
    gridN = list(grid)
    for i in range(width):
        gridN.append([])
        for j in range(height):
            gridN[i].append(cell())
            gridN[i][j].den = 3
    print(gridN[0][0].den)
    
grid[0][0].den = 100
diffuse(0.5,grid)
for y in grid:
    print([x.den for x in y])
    
# Output
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

 

Its first modification will be entry [0, 0] (the value you set to 100), which is thus reset to 0.

ok thx

Link to comment
Share on other sites

Link to post
Share on other sites

You should read up about python deep copy vs shallow copy. Basically python variables work like references so setting array A equal to array B would copy the pointers to each sub array of B into A.

 

Using .copy would copy the references one level deeper. If you actually want to clone the values of arbitrary n-dimensional lists you need to recursively .copy or import deepcopy.

This is a signature.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×