Python中意外的列表理解行为

2024-04-16 08:18:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我相信我被嵌套的范围界定规则和列表理解的结合所困扰。Jeremy Hylton's blog post是关于原因的暗示,但我对CPython的实现还不太了解,无法找到解决这个问题的方法。在

这是一个(过于复杂?)例子。如果人们有一个简单的演示它,我想听听。问题是:使用next()的列表理解将填充上一次迭代的结果。在

编辑:问题:

这到底是怎么回事,我该怎么解决?我必须使用标准for循环吗?显然,函数运行的次数是正确的,但是列表的理解结果是最终的值,而不是每个循环的结果。在

一些假设:

  • 发电机?在
  • 懒散地填写清单理解?在

编码

import itertools
def digit(n):
    digit_list = [ (x,False) for x in xrange(1,n+1)]
    digit_list[0] = (1,True)
    return itertools.cycle ( digit_list)
^{pr2}$
class counter(object):
    def __init__(self):
        self.counter = [ digit(4) for ii in range(2) ] 
        self.totalcount=0
        self.display = [0,] * 2
    def next(self):
        self.totalcount += 1
        self.display[-1] = self.counter[-1].next()[0]
        print self.totalcount, self.display
        return self.display

    def next2(self,*args):
        self._cycle(1)
        self.totalcount += 1
        print self.totalcount, self.display
        return self.display

    def _cycle(self,digit):
        d,first = self.counter[digit].next()
        #print digit, d, first
        #print self._display
        self.display[digit] = d
        if first and digit > 0:
            self._cycle(digit-1)


C = counter()
[C.next() for x in range(5)]
[C.next2() for x in range(5)]

输出

In [44]: [C.next() for x in range(6)]
1 [0, 1]
2 [0, 2]
3 [0, 3]
4 [0, 4]
5 [0, 1]
6 [0, 2]
Out[44]: [[0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2]]

In [45]: [C.next2() for x in range(6)]
7 [0, 3]
8 [0, 4]
9 [1, 1]
10 [1, 2]
11 [1, 3]
12 [1, 4]
Out[45]: [[1, 4], [1, 4], [1, 4], [1, 4], [1, 4], [1, 4]]

# this should be:  [[0,3],[0,4]....[1,4]] or similar

Tags: inself列表forreturndefdisplaycounter
2条回答

问题是使用return self.display返回一个对该列表的引用(而不是副本)。最后得到的是一个列表,其中每个元素都是引用自我展示. 为了说明这一点,请看以下内容:

>>> a = [1,2]
>>> b = [a,a]
>>> b
[[1, 2], [1, 2]]
>>> a.append(3)
>>> b
[[1, 2, 3], [1, 2, 3]]

您可能需要使用return self.display[:]之类的东西。在

介意我重构一下吗?在

def digit(n):
    for i in itertools.count():
        yield (i%n+1, not i%n)

但实际上,如果您将整个过程实现为一个简单的迭代器,则不需要它:

^{pr2}$

如果你想摆脱打印(调试,是吗?),执行while循环。在

这同时也解决了您最初的问题,因为reversed返回了列表的一个副本。在

哦,现在是零基;)

相关问题 更多 >