python递归生成器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python递归生成器相关的知识,希望对你有一定的参考价值。

neted=[[1,2],[3,4],[5]]
def flatten(nested):
try:
for sublist in nested:
for element in flatten(sublist) #我想问一下程序走到这里的时候程序进行迭代
yield element #是不是永远就不会执行到这一句那么这句有什么用?
except TypeError:
yield nested

def dg(value):
for i in range(value):
print 'first',i,'pr',value
for y in dg(i):
print 'second',y #讲这个也行比较容易理解,我想问的就是print 不会这行那 yield y 有什么用? 如 果有值应该是什么?
yield y

>>> for i in dg(2):
a=1
first 0 value 2
first 1 value 2
first 0 value 1

def flattern(nested):
    try:
        if type(nested)==type(""):
            raise TypeError()
        for sublist in nested:
            for element in flattern(sublist):
                yield element
    except TypeError:
        yield nested
nested=[[1,2],[3,4],[5],6]
for i in flattern(nested):
    print i

生成器的作用就是产生一个可迭代对象,可以在for这样的语句中使用,yield element语句的作用就是将element添加到这个可迭代对象

def flattern(nested):
   try:
       for sublist in nested:
           for element in flattern(sublist):  #迭代flattern(子列表)所产生的生成器
               yield element        #对flattern的递归调用只是生成了新的生成器,得将这些生成器中的值添加到当前生成器
   except TypeError:
       yield nested      #如果变量nested不可迭代,for语句会出现TypeError错误,这时将nested添加到当前生成器中

在try开头加上了

if type(nested)==type(""):

    raise TypeError()

因为字符是一直可以迭代的,如果不处理,如果参数中有字符串会无限递归下去

这个函数的作用就是将子列表完全扩展开产生一个生成器

参考技术A flatten和dg函数都没有返回列表,只是返回了none。我完全不懂你用for来遍历它们是什么意思。

Python 是不是具有用于一阶递归关系的迭代递归生成器函数?

【中文标题】Python 是不是具有用于一阶递归关系的迭代递归生成器函数?【英文标题】:Does Python have an iterative recursion generator function for first-order recurrence relations?Python 是否具有用于一阶递归关系的迭代递归生成器函数? 【发布时间】:2016-06-09 23:15:39 【问题描述】:

是否有内置函数或标准库函数大致相当于

def recur_until(start, step_fu, stop_predicate=lambda _: False):
    current = start
    while not stop_predicate(current):
        yield current
        current = step_fu(current)

def recur_while(start, step_fu, predicate=lambda _: True):
    current = start
    while predicate(current):
        yield current
        current = step_fu(current)

甚至只是

def recur(start, step_fu):
    current = start
    while True:
        yield current
        current = step_fu(current)

在任何版本的 Python 中? (后者与itertools.takewhile结合使用时与其他两个一样好。)

像这样的生成器函数将允许迭代地计算某些递归定义的序列,即一阶递归关系。

虽然这些在需要时实施起来并不难,但我觉得它们应该是itertools or maybe functools 的一部分,但如果是,我还无法在文档中找到它。


使用示例:

list(recur_until(2, lambda x: x**2 - 1, lambda x: x > 1e4))
# [2, 3, 8, 63, 3968]

也应该适用于非数字元素:

list(recur_until('', lambda x: '[]()'.format(x, len(x)), lambda x: len(x) > 30))
# ['',
#  '[](0)',
#  '[[](0)](5)',
#  '[[[](0)](5)](10)',
#  '[[[[](0)](5)](10)](16)',
#  '[[[[[](0)](5)](10)](16)](22)']

【问题讨论】:

即等效于 Haskell 的 iterate 函数。 iterate (\x -> x + 1) 0 = 0, 1, 2, 3, 4, 5, ... @chepner iteratetakeWhile 结合使用。 我不知道如何处理“X 存在吗?”这样的问题。我相信答案是“不”。除了链接到您已链接的文档之外,我无法证明该答案的合理性。 @SvenMarnach 是的。我专注于 itertools 中缺少的部分,但您确实需要 iteratetake,dropwhile 的组合。 @DSM,是的,我知道存在问题的问题是否定答案基本上无法证明。但由于我对标准库在这里提供的内容特别感兴趣,所以我不知道如何以不同的方式提出我的问题。 【参考方案1】:

在 Python 3.3+ 中,新的 itertools.accumulate 可以与其他 itertools 结合使用来实现此目的

例如:

>>> from itertools import accumulate, repeat, takewhile
>>> fun = accumulate(range(2, 10), lambda x, _: x**2 - 1)
>>> list(fun)
[2, 3, 8, 63, 3968, 15745023, 247905749270528, 61457260521381894004129398783]
>>> fun = takewhile(lambda y: y < 1e4, accumulate(repeat(2), lambda x, _: x**2 - 1))
>>> list(fun)
[2, 3, 8, 63, 3968]

accumulate 接受一个序列和一个带有 2 个参数的函数:第一个是累加值,第二个是序列中的下一个值。在这种情况下,我们只需要第一个参数,它将是传递给accumulate 的序列的第一个元素,用于第一次调用传递的函数,以及该函数的返回值用于后续调用。

因此,我们只需要将传递序列的开头作为我们的初始值——在本例中为2。序列其余部分的内容无关紧要,但我们可以使用它的长度来控制我们想要多少元素(如第一个示例)或创建一个无限生成器(如第二个示例)。

【讨论】:

嘿,在我看到你的答案之前不久,我刚刚启动了另一台装有 Python 3.4 的计算机来测试类似的东西。【参考方案2】:

缺少的链接是您需要一些东西来将递归步进函数转换为生成器。一旦你有了它,你就可以使用任何 itertools 方法。

def recur_to_gen(step_fu, current, sentinel=None):
    while current != sentinel:
        yield current
        current = step_fu(current)


matches = itertools.takewhile(predicate, recur_to_gen(step_fu, start))

recur_to_gen 建议添加到itertools 可能是合理的。

【讨论】:

通常称为iterate,例如在 Haskell 或 functional Python library. 不幸的是,我认为 Python 中的“迭代”与 iter 密切相关,这更多是关于通过一个序列进行步进,而不是递归地将步进函数应用于一个项目以获得下一个项目.但不管叫什么名字,我认为itertools 会是这样的好地方。 @StefanPochmann 函数recur_to_gen() 是一个生成器函数(因为它是yields)。这里没有生成器表达式。 @SvenMarnach:我认为 SP 引起了人们对 PM 第一句话的注意——OP 的原始函数(虽然称为 recur)是非递归的,并且已经是一个 genfunc。 @DSM - 在它调用自身的意义上不是递归的,但它通过调用当前项目上的步进函数来遍历一个不必要连续的项目链以获得下一个。【参考方案3】:

functional 包提供了模拟这个的部分。

from functional import dropWhile, iterate    
recur = dropWhile(predicate, iterate(step_func, start))

例如,

>>> next(dropWhile(lambda x : x < 10, iterate(lambda x: x + 1, 2)))
10

dropWhileitertools.dropwhile 并没有什么不同。)

【讨论】:

最新的可用版本适用于 Python 2.5。更新的 Python 功能包:github.com/kachayev/fn.py 它仍然有效(通过pip 安装,但我没有对其进行广泛测试)但是是的,我认为functional 是一次性的概念验证,从未真正得到支持.

以上是关于python递归生成器的主要内容,如果未能解决你的问题,请参考以下文章

python学习week5-递归,匿名函数生成器

Python 是不是具有用于一阶递归关系的迭代递归生成器函数?

Python实现JSON生成器和递归下降解释器

python函数递归和生成器

python 生成器和递归

python--递归函数匿名函数嵌套函数高阶函数装饰器生成器迭代器