0

I am making a certain class for specific purpose ( this time partilce simulation ) when I declare two distinict objects with that class, they themselves share different memory addresses, but their attributes share THE SAME address, which leads to modifying any of them to modify the other, any help? I am stuck.

The code logic-error block:

# Particle is the class
particle1 = Particle(m = 2)
particle2 = Particle(m = 4)
# object.S is an atrribute
particle1.S[1]=np.array([0,1,32])
particle2.S[1]=np.array([2,0,3])
hex(id(particle1.S))==hex(id(particle2.S)) # returns True

And here it is the constructor:

def __init__(self, m = 0, Q = 0, initS = np.array([[0,0,0],[0,0,0],[0,0,0]]) ):
        self.initS = initS
        self.S = self.initS
        self.m = m; self.t = 0
        self.charge = Q
AGawish
  • 98
  • 1
  • 6
  • 1
    Please show the constructor. It's possible the S you make is common across the objects (e.g. you have a mutable default value). – h4z3 Jul 10 '19 at 11:58
  • done, the constructor has been added. – AGawish Jul 10 '19 at 12:17
  • Yes, `initS` has a mutable default argument; just as h4z3 expected. All instances created without explicitly passing a value for `initS` share the same NumPy array. – shmee Jul 10 '19 at 12:36

1 Answers1

0

Okay, just as I expected in the comments, you have a mutable default argument.

The behaviour of a default mutable argument is a very interesting (as in: veeeery confusing but in fact logical) thing but you can read about them here.

What you need to know is: never use mutable things as default arguments. Use None instead and check it in the body:

def __init__(self, m = 0, Q = 0, initS = None ):
        self.initS = initS if initS else np.array([[0,0,0],[0,0,0],[0,0,0]]) #here
        self.S = self.initS
        self.m = m; self.t = 0
        self.charge = Q

As a default argument np.array([[0,0,0],[0,0,0],[0,0,0]]) is created only once and reused. Using None and inline if/else, you make sure to create a new instance each time the constructor is created.

Use this approach with every default argument that is mutable - lists, dictionaries, sets... or your own classes to avoid this problem in the future.

h4z3
  • 5,265
  • 1
  • 15
  • 29