使用 yield from 重构阶乘实现,产生了意想不到的结果

Using yield from to refactor a factorial implementation, yielded unexpected results

下面的第一个函数使用 yield 语句实现阶乘函数的递归版本。

我试图在此 factorial() 中应用 yield from 语句,以便进行实验和学习。 因此,我编写了 factorial2() 函数,尽管它打印了正确的阶乘,但它并没有打印所有以前的值,例如 factorial().

我想知道是否有任何方法可以在 factorial2() 中获得与 factorial() 完全相同的功能?

def factorial(n):
    if n == 1:
        yield 1
    else:
        for u in factorial(n - 1):
            yield u
        yield u * n

def factorial2(n):
    if n == 1:
        yield 1
    else:
        yield from (i * n for i in factorial2(n - 1))

def main():
    for u in factorial(12):
        print(u)
    for a in factorial2(12):
        print(a)

if __name__ == '__main__': main()

输出:

1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
479001600

预期输出:(与factorial()相同)

1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600

您的 factorial2 代码等同于:

# wrong code, do not use
def factorial2(n):
    if n == 1:
        yield 1
    else:
        for i in factorial2(n - 1):
            yield i * n

我希望你能明白为什么这不起作用。

相反,您可以尝试使用 zip and itertools.count.

从另一方面解决这个问题
from itertools import count

def factorial3(n):
    yield 1
    if n > 1:
        yield from (u * i for u, i in zip(factorial3(n - 1), count(2)))

您可以在生成器中使用 return 值来做到这一点,这就是 yield from 表达式最终 return:

def factorial2(n):
    if n == 1:
        f = 1
    else:
        a = yield from factorial2(n - 1)
        f = n * a
    # Yielded by the generator
    yield f
    # Returned to `yield from`
    return f

for a in factorial2(12):
    print(a)
# 1
# 2
# 6
# 24
# 120
# 720
# 5040
# 40320
# 362880
# 3628800
# 39916800
# 479001600