【问题标题】:Scope of Python Recursive GeneratorsPython 递归生成器的范围
【发布时间】:2010-10-25 10:38:25
【问题描述】:

大家好,我正在使用递归生成器来创建数字的固定整数分区,但我对范围问题感到困惑。

代码类似于这个sn-p。

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

我的困惑如下图。

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

我可以通过使用数组的副本来获得正确的答案(例如,将a[:] 传递给递归调用)但我仍然不明白上述行为。 为什么 print 语句和 yield 值不一样?

【问题讨论】:

    标签: python recursion scope generator


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      print 和 yield 语句不同,因为您只有一个 print 语句,而您有 2 个 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]]
      

      您会看到最后的产量是您的答案,因为您一直在传递相同的列表而不是复制。

      【讨论】:

        【解决方案3】:

        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]
        

        【讨论】:

          【解决方案4】:

          我猜你正在改变数组,所以当你打印它时它有一个特定的值,然后你下次打印它实际​​上更新了这个值,等等。最后,你有 5 次对同一个数组的引用,所以当然你有 5 次相同的值。

          【讨论】:

          • a[i] += n 肯定会改变数组。
          猜你喜欢
          • 2021-05-22
          • 2016-05-03
          • 2012-05-03
          • 2013-09-16
          • 2013-05-19
          • 1970-01-01
          • 2017-06-26
          • 2016-04-03
          • 1970-01-01
          相关资源
          最近更新 更多