Reputation: 8057
I'm not really sure what is going on here. But the elements in my list keep changing.
table._row_gen
is a generator instance, and it creates the rows for my table. Source is here.
It returns a dict
; I can also get the dict
directly from table._row_gen.stats
.
def test_append(self):
start_stats = {'step':250,'offset':13,'inc':113,'danger':0,'input':None}
gen = StatGenerator(start_stats)
table = PathTable(gen)
stats_list = []
for i in xrange(50):
stats_list.append(table._row_gen.stats)
print stats_list[i]
table._row_gen.next()
assert stats_list[0]['step'] == 250
This should build a list of rows to stats_list
.
The print
works fine and displays the correct output:
{'danger': 0, 'input': None, 'step': 250, 'inc': 113, 'offset': 13}
{'enc': False, 'danger': 113, 'rnd': 216, 'step': 252, 'limit': 55552, 'offset': 13, 'inpu
{'enc': False, 'danger': 226, 'rnd': 163, 'step': 254, 'limit': 41984, 'offset': 13, 'inpu
{'enc': False, 'danger': 339, 'rnd': 151, 'step': 0, 'limit': 38912, 'offset': 26, 'input'
{'enc': False, 'danger': 452, 'rnd': 212, 'step': 2, 'limit': 54528, 'offset': 26, 'input'
{'enc': False, 'danger': 565, 'rnd': 64, 'step': 4, 'limit': 16640, 'offset': 26, 'input'
But the list is malformed, and the assert
fails:
> assert stats_list[0]['step'] == 250
E assert 94 == 250
test_int_path_table.py:47: AssertionError
After the loop:
print stats_list[0]
{'enc': True, 'danger': 5650, 'rnd': 6, 'step': 94, 'limit': 1792, 'offset': 26, 'input':
94 should the last row. Yet all of the rows are reporting to be the same:
print stats_list[0] is stats_list[48]
True
I don't really understand why this is happening, and I would like the list to be correct (like the print
output).
Upvotes: 0
Views: 81
Reputation: 8845
The simple solution is to make a copy. For this, you can do
def test_append(self):
start_stats = {'step':250,'offset':13,'inc':113,'danger':0,'input':None}
gen = StatGenerator(start_stats)
table = PathTable(gen)
stats_list = []
for i in xrange(50):
stats_list.append(table._row_gen.stats.copy()) # <=== the copy call makes a new copy and solves your problem.
print stats_list[i]
table._row_gen.next()
assert stats_list[0]['step'] == 250
Also, the next
call at the end of the for block is extraneous. It can be combined using
def test_append(self):
start_stats = {'step':250,'offset':13,'inc':113,'danger':0,'input':None}
gen = StatGenerator(start_stats)
table = PathTable(gen)
stats_list = []
for i in xrange(50):
stats_list.append(next(table._row_gen).copy())
print stats_list[i]
assert stats_list[0]['step'] == 250
If you're in control of the pastebin code, the stats property should return a defensive copy.
@property
def stats(self):
return self._stats.copy()
and the next
method should return a defensive copy too.
def next(self):
''' Generates and returns stats. '''
row = self._stats
row['step'] = self._genStepId(self._stats['step'])
row['offset'] = self._genOffset(self._stats['offset'], self._stats['step'])
row['danger'] = self._genDanger(self._stats['danger'], self.stats['inc'])
row['rnd'] = self._genRnd(self.rnlut[self._stats['step']], self._stats['offset'])
row['limit'] = self._genDangerLimit(self._stats['rnd'])
row['enc'] = self._genEnc(self._stats['danger'], self._stats['limit'])
return self.stats
If you do the above two blocks, the copy in the first two is no longer necessary.
Upvotes: 1