S. Gamgee S. Gamgee - 3 months ago 6
Python Question

Objects retain info from previous loop iteration

I have a class called

run_c
which is being used to initialize and execute the run of a kinematics simulation. I assign default values to the attributes of
run_c
, such as
x
, before
run_c.__init__()
is executed. All
__init__()
is doing is extracting user-input values, aggregated into a dictionary, and assigning them to corresponding attributes in
run_c
if they exists. For example...

import vars.Defaults as dft
class run_c:

...
dt = dft.dt
x = dft.x0
states = [ [], [], [], [] ]
...

def __init__(self, input):
for key in input.keys():
if hasattr(self, key): setattr(self, key, input[key])
...
self.execute()


run_c.states
is a list of lists that is being used to record the values of
run_c
attributes as they change with timesteps. Later, within
run_c.execute()
, I am storing
x
values in
states[1]
, incrementing the timestep
dt
, and updating
x
using velocity and timestep. It's pretty simple stuff, right?...

Here's where the problem begins, though. The first time that the instance of
run_c
is created, initialized, and executed, it runs perfectly. However, I am operating this simulation by creating, initializing, and executing multiple runs based off of list read from a JSON file. As such, in the driver module...

from Run import run_c
def main():
...
for runEntry in runList:
currRun = run_c(runEntry)
...
...


What happens is that all the values that were stored in
run_c.states
do not get wiped after each iteration of the loop. I thought that new instances of
run_c
are being created every time I run the loop so as to execute
__init__()
fresh with new information. Why are the data values, such as old values for
x
, being retained after the end of each loop?

Update: When I add in a line of code to reset the values of
states
back to empty lists within
__init__()
, the problem goes away. But this shouldn't be a necessary step in what I want to do...should it?

Answer

dt, x, and states are defined as class variables, not instance variables. Every instance of that class that you make will share them. If you need them to be initialized each time you generate a new instance, that's exactly what __init__() is for:

class run_c:

   def __init__(self, input):
      ...
      self.dt     = dft.dt
      self.x      = dft.x0
      self.states = [ [], [], [], [] ]
      ...

      for key in input.keys():
         if hasattr(self, key): setattr(self, key, input[key])
      ...
      self.execute()
Comments