如何阻止列表中的元素更改?

时间:2015-04-08 17:55:36

标签: python

我不确定这里发生了什么。但是我列表中的元素不断变化。

table._row_gen是一个生成器实例,它为我的表创建行。来源是here

返回dict;我也可以直接从dict获取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

这应该构建一个到stats_list的行列表。

print正常工作并显示正确的输出:

{'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'

但是列表格式不正确,assert失败了:

>           assert stats_list[0]['step'] == 250
E           assert 94 == 250

test_int_path_table.py:47: AssertionError

循环后:

print stats_list[0]
{'enc': True, 'danger': 5650, 'rnd': 6, 'step': 94, 'limit': 1792, 'offset': 26, 'input':

94应该是最后一行。然而,所有行报告都是相同的:

print stats_list[0] is stats_list[48]
True

我真的不明白为什么会这样,我希望列表正确(如print输出)。

1 个答案:

答案 0 :(得分:1)

简单的解决方案是制作副本。为此,你可以做到

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

此外,for块末尾的next调用是无关紧要的。它可以使用

组合
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

如果你控制了pastebin代码,stats属性应该返回一个防御性副本。

    @property
    def stats(self):
            return self._stats.copy()

并且next方法也应该返回防御性副本。

    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

如果您执行上述两个区块,则不再需要前两个区域中的副本。