0

I am trying to store dictionaries in one master dictionary, as a way to store the history of variables, so that they can be accessed later, if need be.

I define the dictionaries as such:

self.current = {}
self.version = {}

self.current will store two key/value pairs that will map the words nodes to a current nodes SQL table and the word edges to a current edges SQL table.

As the program iterates through, it makes new tables to represent the edges and nodes in the system, and so I would like to store self.current itself as a value in self.version, such that a time variable can access the state of the system at any past time step.

For example, if there are 10 iterations in total, than self.current['nodes'] should return 'dhn_vertices_pgr9' and self.current['edges'] should return 'dhn9'

I am doing this like this:

self.version[time] = self.current

At the end of each iteration. Howevever, every single time, the self.version table has the most recent dictionary mapped to every single time step:

With print statements:

print('iteration {0}, current nodes = {1}'.format(time, self.current['nodes']))
print('iteration {0}, current edges = {1}'.format(time, self.current['edges']))
print('iteration {0}, time = {1}'.format(time, time))
print('iteration {0}, self.current = {1}'.format(time, self.current))
self.version[time] = self.current
print('iteration {0}, self.version = {1}\n'.format(time, self.version))

Shows in the console:

iteration 0, current nodes = dhn_0_vertices_pgr
iteration 0, current edges = dhn_0
iteration 0, time = 0
iteration 0, self.current = {'edges': 'dhn_0', 'nodes': 'dhn_0_vertices_pgr'}
iteration 0, self.version = {0: {'edges': 'dhn_0', 'nodes': 'dhn_0_vertices_pgr'}}

iteration 1, current nodes = dhn_1_vertices_pgr
iteration 1, current edges = dhn_1
iteration 1, time = 1
iteration 1, self.current = {'edges': 'dhn_1', 'nodes': 'dhn_1_vertices_pgr'}
iteration 1, self.version = {0: {'edges': 'dhn_1', 'nodes': 'dhn_1_vertices_pgr'}, 1: {'edges': 'dhn_1', 'nodes': 'dhn_1_vertices_pgr'}}

iteration 2, current nodes = dhn_2_vertices_pgr
iteration 2, current edges = dhn_2
iteration 2, time = 2
iteration 2, self.current = {'edges': 'dhn_2', 'nodes': 'dhn_2_vertices_pgr'}
iteration 2, self.version = {0: {'edges': 'dhn_2', 'nodes': 'dhn_2_vertices_pgr'}, 1: {'edges': 'dhn_2', 'nodes': 'dhn_2_vertices_pgr'}, 2: {'edges': 'dhn_2', 'nodes': 'dhn_2_vertices_pgr'}}

iteration 3, current nodes = dhn_3_vertices_pgr
iteration 3, current edges = dhn_3
iteration 3, time = 3
iteration 3, self.current = {'edges': 'dhn_3', 'nodes': 'dhn_3_vertices_pgr'}
iteration 3, self.version = {0: {'edges': 'dhn_3', 'nodes': 'dhn_3_vertices_pgr'}, 1: {'edges': 'dhn_3', 'nodes': 'dhn_3_vertices_pgr'}, 2: {'edges': 'dhn_3', 'nodes': 'dhn_3_vertices_pgr'}, 3: {'edges': 'dhn_3', 'nodes': 'dhn_3_vertices_pgr'}}

As you can see, every value in self.version is just the latest entry.

But what does not make sense to me, is that if I simply save both entries as a tuple like so:

self.version[time] = (self.current['edges'], self.current['nodes'])

And again with print statements:

print('iteration {0}, current nodes = {1}'.format(time, self.current['nodes']))
print('iteration {0}, current edges = {1}'.format(time, self.current['edges']))
print('iteration {0}, time = {1}'.format(time, time))
print('iteration {0}, self.current = {1}'.format(time, self.current))
self.version[time] = (self.current['edges'], self.current['nodes'])
print('iteration {0}, self.version = {1}\n'.format(time, self.version))

Gives the console output:

iteration 0, current nodes = dhn_0_vertices_pgr
iteration 0, current edges = dhn_0
iteration 0, time = 0
iteration 0, self.current = {'edges': 'dhn_0', 'nodes': 'dhn_0_vertices_pgr'}
iteration 0, self.version = {0: ('dhn_0', 'dhn_0_vertices_pgr')}

iteration 1, current nodes = dhn_1_vertices_pgr
iteration 1, current edges = dhn_1
iteration 1, time = 1
iteration 1, self.current = {'edges': 'dhn_1', 'nodes': 'dhn_1_vertices_pgr'}
iteration 1, self.version = {0: ('dhn_0', 'dhn_0_vertices_pgr'), 1: ('dhn_1', 'dhn_1_vertices_pgr')}

iteration 2, current nodes = dhn_2_vertices_pgr
iteration 2, current edges = dhn_2
iteration 2, time = 2
iteration 2, self.current = {'edges': 'dhn_2', 'nodes': 'dhn_2_vertices_pgr'}
iteration 2, self.version = {0: ('dhn_0', 'dhn_0_vertices_pgr'), 1: ('dhn_1', 'dhn_1_vertices_pgr'), 2: ('dhn_2', 'dhn_2_vertices_pgr')}

iteration 3, current nodes = dhn_3_vertices_pgr
iteration 3, current edges = dhn_3
iteration 3, time = 3
iteration 3, self.current = {'edges': 'dhn_3', 'nodes': 'dhn_3_vertices_pgr'}
iteration 3, self.version = {0: ('dhn_0', 'dhn_0_vertices_pgr'), 1: ('dhn_1', 'dhn_1_vertices_pgr'), 2: ('dhn_2', 'dhn_2_vertices_pgr'), 3: ('dhn_3', 'dhn_3_vertices_pgr')}

As you can see, time step 1 now actually maps to the table names as they were in time step 1, time step 2 maps to the table names as in time step 2, table names in 3 to time step 3, etc...

So why is it that doing this in a dictionary causes it to fail, when doing it with tuples works perfectly fine?

wfgeo
  • 2,716
  • 4
  • 30
  • 51

1 Answers1

2

When you assign

self.version[time] = (self.current)

You do not assign the value of the dict, but a reference to the same dict. Consider the following example:

dictA = {}
dictB = {}
dictA = dictB
dictB['foo'] = 'bar'
print(dictA) //{'foo': 'bar'}
print(dictB) //{'foo': 'bar'}

In this example, when you assign dictA = dictB you point both dictA and dictB to the same object. So changing dictB will also change dictA (and the opposite) To fix this, you instead want to copy the value of dictB (and not the reference). And you do this by dict(dictB) according to:

dictA = {}
dictB = {}
dictA = dict(dictB) //the value of dictB is now copied, not the reference
dictB['foo'] = 'bar'
print(dictA) //{}
print(dictB) //{'foo': 'bar'}

Back to your example: Change self.current will also affect self.version. So to fix this change to:

self.version[time] = dict(self.current)

See How to copy a dictionary and only edit the copy

Community
  • 1
  • 1
Cleared
  • 2,490
  • 18
  • 35
  • thank you, this was exactly what i needed. i have been puzzling over this for the greater part of an hour, i knew it had to be something simple like this. – wfgeo May 09 '17 at 14:26