Python中意外的列表理解行为

Python中意外的列表理解行为,python,list-comprehension,language-implementation,Python,List Comprehension,Language Implementation,我相信我正被嵌套的范围规则和列表理解的组合所困扰。是关于原因的暗示,但我对CPython的实现还不太了解,不知道如何解决这个问题 下面是一个(过于复杂?)的例子。如果人们有一个更简单的演示,我想听听。问题是:使用next()的列表理解将由上一次迭代的结果填充 编辑:问题: 这到底是怎么回事,我该如何解决?我必须使用循环的标准吗?很明显,函数运行的次数是正确的,但是列表理解最终得到的是最终值,而不是每个循环的结果 一些假设: 发电机 懒散地填写清单理解 代码 import itertools

我相信我正被嵌套的范围规则和列表理解的组合所困扰。是关于原因的暗示,但我对CPython的实现还不太了解,不知道如何解决这个问题

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

编辑:问题:

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

一些假设:

  • 发电机
  • 懒散地填写清单理解
代码

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)
输出

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 在[44]中:[C.next()表示范围(6)中的x] 1 [0, 1] 2 [0, 2] 3 [0, 3] 4 [0, 4] 5 [0, 1] 6 [0, 2] 输出[44]:[0,2],[0,2],[0,2],[0,2],[0,2],[0,2],[0,2]] 在[45]中:[C.next2()表示范围(6)中的x] 7 [0, 3] 8 [0, 4] 9 [1, 1] 10 [1, 2] 11 [1, 3] 12 [1, 4] 出[45]:[1,4],[1,4],[1,4],[1,4],[1,4],[1,4],[1,4]] #这应该是:[[0,3],[0,4]…[1,4]]或类似的
问题是,使用
返回self.display
返回对此列表的引用(而不是副本)。因此,最终得到的是一个列表,其中每个元素都是对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)
但实际上,如果您将整个过程实现为一个简单的迭代器,则不需要该迭代器:

def counter(digits, base):
    counter = [0] * digits

    def iterator():
        for total in itertools.count(1):
            for i in range(len(counter)):
                counter[i] = (counter[i] + 1) % base
                if counter[i]:
                    break
            print total, list(reversed(counter))
            yield list(reversed(counter))

    return iterator()

c = counter(2, 4)
print list(itertools.islice(c, 10))
如果您想摆脱打印(调试,是吗?),请使用while循环

这也解决了最初的问题,因为
reversed
返回列表的副本


哦,现在是零基;)

对不起,有什么问题吗?
def digit(n):
    for i in itertools.count():
        yield (i%n+1, not i%n)
def counter(digits, base):
    counter = [0] * digits

    def iterator():
        for total in itertools.count(1):
            for i in range(len(counter)):
                counter[i] = (counter[i] + 1) % base
                if counter[i]:
                    break
            print total, list(reversed(counter))
            yield list(reversed(counter))

    return iterator()

c = counter(2, 4)
print list(itertools.islice(c, 10))