当递归函数也是生成器时实际发生了什么?
What actually happens when a recursive function is also a generator?
我正在编写一个函数,给定一个数组,returns 一个可能的排列列表。
我想出了以下方法并且效果很好:
def _permutate(elems):
if len(elems) <= 1:
yield elems
else:
for i in range(len(elems)):
for perm in _permutate(elems[:i] + elems[i+1:]):
yield [elems[i]] + perm
所以 运行 print(list(_permutate([2, 1, 3])))
给我:[[2, 1, 3], [2, 3, 1], [1, 2, 3], [1, 3, 2], [3, 2, 1], [3, 1, 2]]
但我想知道后台实际发生了什么...
我知道一个递归函数会添加到堆栈中,直到它到达它的基本情况,然后在堆栈中向后工作以给你一个结果,然后一个生成器函数在它的第一个 yield 和 returns 你有一个生成器时暂停计算循环获取每个产量的结果,但我真的很困惑当你把两者放在一起时会发生什么。
用调试语句重写函数
def _permutate(elems):
if len(elems) <= 1:
print(elems) # NEW
yield elems
else:
for i in range(len(elems)):
for perm in _permutate(elems[:i] + elems[i+1:]):
print("NEW", [elems[i]], perm) # NEW
yield [elems[i]] + perm
然后运行
gen = _permutate([1,2,3,4,5])
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
更清楚地显示发生了什么:
[5]
NEW [4] [5]
NEW [3] [4, 5]
NEW [2] [3, 4, 5]
NEW [1] [2, 3, 4, 5]
NEXT [1, 2, 3, 4, 5]
[4]
NEW [5] [4]
NEW [3] [5, 4]
NEW [2] [3, 5, 4]
NEW [1] [2, 3, 5, 4]
NEXT [1, 2, 3, 5, 4]
[5]
NEW [3] [5]
NEW [4] [3, 5]
NEW [2] [4, 3, 5]
NEW [1] [2, 4, 3, 5]
NEXT [1, 2, 4, 3, 5]
[3]
NEW [5] [3]
NEW [4] [5, 3]
NEW [2] [4, 5, 3]
NEW [1] [2, 4, 5, 3]
NEXT [1, 2, 4, 5, 3]
[4]
NEW [3] [4]
NEW [5] [3, 4]
NEW [2] [5, 3, 4]
NEW [1] [2, 5, 3, 4]
NEXT [1, 2, 5, 3, 4]
[3]
NEW [4] [3]
NEW [5] [4, 3]
NEW [2] [5, 4, 3]
NEW [1] [2, 5, 4, 3]
NEXT [1, 2, 5, 4, 3]
[5]
NEW [4] [5]
NEW [2] [4, 5]
NEW [3] [2, 4, 5]
NEW [1] [3, 2, 4, 5]
NEXT [1, 3, 2, 4, 5]
找到一篇文章 here,其中显示了 table 在递归生成器期间发生的事情。
我试过用数组 [1,2,3] 重新创建这个 table
我做了一个实验来说明生成器的流程是如何工作的:
def _permutate(elems):
if len(elems) <= 1:
print(elems) # NEW
yield elems
else:
for i in range(len(elems)):
for perm in _permutate(elems[:i] + elems[i+1:]):
print([elems[i]] + perm) # NEW
yield [elems[i]] + perm
# NEW
gen = _permutate([1,2,3,4,5])
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
输出:
[5]
[4, 5]
[3, 4, 5]
[2, 3, 4, 5]
[1, 2, 3, 4, 5]
NEXT [1, 2, 3, 4, 5]
[4]
[5, 4]
[3, 5, 4]
[2, 3, 5, 4]
[1, 2, 3, 5, 4]
NEXT [1, 2, 3, 5, 4]
[5]
[3, 5]
[4, 3, 5]
[2, 4, 3, 5]
[1, 2, 4, 3, 5]
NEXT [1, 2, 4, 3, 5]
[3]
[5, 3]
[4, 5, 3]
[2, 4, 5, 3]
[1, 2, 4, 5, 3]
NEXT [1, 2, 4, 5, 3]
[4]
[3, 4]
[5, 3, 4]
[2, 5, 3, 4]
[1, 2, 5, 3, 4]
NEXT [1, 2, 5, 3, 4]
[3]
[4, 3]
[5, 4, 3]
[2, 5, 4, 3]
[1, 2, 5, 4, 3]
NEXT [1, 2, 5, 4, 3]
[5]
[4, 5]
[2, 4, 5]
[3, 2, 4, 5]
[1, 3, 2, 4, 5]
NEXT [1, 3, 2, 4, 5]
我正在编写一个函数,给定一个数组,returns 一个可能的排列列表。 我想出了以下方法并且效果很好:
def _permutate(elems):
if len(elems) <= 1:
yield elems
else:
for i in range(len(elems)):
for perm in _permutate(elems[:i] + elems[i+1:]):
yield [elems[i]] + perm
所以 运行 print(list(_permutate([2, 1, 3])))
给我:[[2, 1, 3], [2, 3, 1], [1, 2, 3], [1, 3, 2], [3, 2, 1], [3, 1, 2]]
但我想知道后台实际发生了什么... 我知道一个递归函数会添加到堆栈中,直到它到达它的基本情况,然后在堆栈中向后工作以给你一个结果,然后一个生成器函数在它的第一个 yield 和 returns 你有一个生成器时暂停计算循环获取每个产量的结果,但我真的很困惑当你把两者放在一起时会发生什么。
用调试语句重写函数
def _permutate(elems):
if len(elems) <= 1:
print(elems) # NEW
yield elems
else:
for i in range(len(elems)):
for perm in _permutate(elems[:i] + elems[i+1:]):
print("NEW", [elems[i]], perm) # NEW
yield [elems[i]] + perm
然后运行
gen = _permutate([1,2,3,4,5])
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
更清楚地显示发生了什么:
[5]
NEW [4] [5]
NEW [3] [4, 5]
NEW [2] [3, 4, 5]
NEW [1] [2, 3, 4, 5]
NEXT [1, 2, 3, 4, 5]
[4]
NEW [5] [4]
NEW [3] [5, 4]
NEW [2] [3, 5, 4]
NEW [1] [2, 3, 5, 4]
NEXT [1, 2, 3, 5, 4]
[5]
NEW [3] [5]
NEW [4] [3, 5]
NEW [2] [4, 3, 5]
NEW [1] [2, 4, 3, 5]
NEXT [1, 2, 4, 3, 5]
[3]
NEW [5] [3]
NEW [4] [5, 3]
NEW [2] [4, 5, 3]
NEW [1] [2, 4, 5, 3]
NEXT [1, 2, 4, 5, 3]
[4]
NEW [3] [4]
NEW [5] [3, 4]
NEW [2] [5, 3, 4]
NEW [1] [2, 5, 3, 4]
NEXT [1, 2, 5, 3, 4]
[3]
NEW [4] [3]
NEW [5] [4, 3]
NEW [2] [5, 4, 3]
NEW [1] [2, 5, 4, 3]
NEXT [1, 2, 5, 4, 3]
[5]
NEW [4] [5]
NEW [2] [4, 5]
NEW [3] [2, 4, 5]
NEW [1] [3, 2, 4, 5]
NEXT [1, 3, 2, 4, 5]
找到一篇文章 here,其中显示了 table 在递归生成器期间发生的事情。
我试过用数组 [1,2,3] 重新创建这个 table
我做了一个实验来说明生成器的流程是如何工作的:
def _permutate(elems):
if len(elems) <= 1:
print(elems) # NEW
yield elems
else:
for i in range(len(elems)):
for perm in _permutate(elems[:i] + elems[i+1:]):
print([elems[i]] + perm) # NEW
yield [elems[i]] + perm
# NEW
gen = _permutate([1,2,3,4,5])
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
print('NEXT', next(gen))
输出:
[5]
[4, 5]
[3, 4, 5]
[2, 3, 4, 5]
[1, 2, 3, 4, 5]
NEXT [1, 2, 3, 4, 5]
[4]
[5, 4]
[3, 5, 4]
[2, 3, 5, 4]
[1, 2, 3, 5, 4]
NEXT [1, 2, 3, 5, 4]
[5]
[3, 5]
[4, 3, 5]
[2, 4, 3, 5]
[1, 2, 4, 3, 5]
NEXT [1, 2, 4, 3, 5]
[3]
[5, 3]
[4, 5, 3]
[2, 4, 5, 3]
[1, 2, 4, 5, 3]
NEXT [1, 2, 4, 5, 3]
[4]
[3, 4]
[5, 3, 4]
[2, 5, 3, 4]
[1, 2, 5, 3, 4]
NEXT [1, 2, 5, 3, 4]
[3]
[4, 3]
[5, 4, 3]
[2, 5, 4, 3]
[1, 2, 5, 4, 3]
NEXT [1, 2, 5, 4, 3]
[5]
[4, 5]
[2, 4, 5]
[3, 2, 4, 5]
[1, 3, 2, 4, 5]
NEXT [1, 3, 2, 4, 5]