Python递归生成器的作用域

Python递归生成器的作用域,python,recursion,scope,generator,Python,Recursion,Scope,Generator,嘿,我正在开发一个递归生成器来创建一个数字的固定整数分区,我被一个范围问题弄糊涂了 代码类似于此代码段 def testGen(a,n): if n <= 1: print('yield', a) yield a else: for i in range(2): a[i] += n for j in testGen(a,n-i-1): yield

嘿,我正在开发一个递归生成器来创建一个数字的固定整数分区,我被一个范围问题弄糊涂了

代码类似于此代码段

def testGen(a,n):
    if n <= 1:
        print('yield', a)
        yield a
    else:
        for i in range(2):
            a[i] += n
            for j in testGen(a,n-i-1):
                yield j
我可以通过使用数组的副本(例如,将
a[:]
传入递归调用)得到正确的答案,但我仍然不理解上述行为。
为什么print语句和yield值不同?

我猜您是在改变数组,所以当您打印它时,它有一个特定的值,然后下次打印时,它实际上更新了该值,依此类推。最后,您有5个对同一数组的引用,因此当然有5次相同的值。

print语句在特定时间点显示列表。您的代码在运行列表时会更改列表,因此在最后检查列表时,您会看到它的值

您可以通过单步执行以下操作来观察这一点:

>>> g = testGen([1,2],4)
>>> g.next()
('yield', [10, 2])   # note brackets in print statement because I'm on python 2.5
[10, 2]
>>> g.next()
('yield', [10, 4])
[10, 4]
>>> g.next()
('yield', [10, 7])
[10, 7]
>>> g.next()
('yield', [12, 11])
[12, 11]
>>> g.next()
('yield', [12, 13])
[12, 13]

print语句和yield语句不同,因为只有一个print语句,而有两个yield语句。试试这个:

def testGen(a,n):
    if n <= 1:
        print('yield', a)
        yield a
    else:
        for i in range(2):
            a[i] += n
            for j in testGen(a,n-i-1):
                print('yield', j)
                yield j

>>> list(testGen([1,2],4))
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 7])
('yield', [10, 7])
('yield', [10, 7])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 13])
('yield', [12, 13])
('yield', [12, 13])
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]]
def testGen(a,n): 如果n>>列表(testGen([1,2],4)) (“收益率”[10,2]) (“收益率”[10,2]) (“收益率”[10,2]) (“收益率”[10,2]) (‘收益率’,[10,4]) (‘收益率’,[10,4]) (‘收益率’,[10,4]) (‘收益率’,[10,4]) (“收益率”[10,7]) (“收益率”[10,7]) (“收益率”[10,7]) (“收益率”[12,11]) (“收益率”[12,11]) (“收益率”[12,11]) (“收益率”[12,13]) (“收益率”[12,13]) (“收益率”[12,13]) [[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]]
您将看到最后的结果是您的答案,因为您一直在传递相同的列表,而不是制作副本。

列表是可变对象,如果您传入一个列表,并且生成器对该列表执行就地操作,那么最后对该列表的所有引用都将指向相同的列表。

a[i]+=n
肯定会使数组发生变异。
def testGen(a,n):
    if n <= 1:
        print('yield', a)
        yield a
    else:
        for i in range(2):
            a[i] += n
            for j in testGen(a,n-i-1):
                print('yield', j)
                yield j

>>> list(testGen([1,2],4))
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 7])
('yield', [10, 7])
('yield', [10, 7])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 13])
('yield', [12, 13])
('yield', [12, 13])
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]]