为什么我的yield
关键字没有产生预期的输出?
我正在使用递归算法(合并排序)并使用yield
,以便每次更改(排序)时都可以遍历列表。
def MergeSort(lst):
if len(lst) > 1:
middle = len(lst)//2
lefthalf = lst[:middle]
righthalf = lst[middle:]
MergeSort(lefthalf)
MergeSort(righthalf)
i,j,k= 0,0,0
while i<len(lefthalf) and j<len(righthalf):
if lefthalf[i] < righthalf[j]:
lst[k] = lefthalf[i]
i+=1
else:
lst[k] = righthalf[j]
j+=1
k+=1
while i<len(lefthalf):
lst[k]=lefthalf[i]
i+=1
k+=1
while j<len(righthalf):
lst[k]=righthalf[j]
j+=1
k+=1
yield lst
a = MergeSort([2,3,566,78,8])
for i in a:
print(i)
[2, 3, 566, 78, 8]
相反,我希望获得类似的结果:(随着算法的工作)
[2, 3, 566, 78, 8]
[2, 3, 566, 8, 78]
[2, 3, 8, 78, 566]
如果我使用return
语句,它将正常工作并按预期对列表进行排序,但是当我使用yield
时,我无法获得适当的生成器。我还尝试将yield
放置在while
语句中以及几乎所有其他地方。我怎样才能解决这个问题?我想念什么?
由于您将MergeSort
设置为生成器,并且生成器是惰性的,因此递归调用实际上不进行任何排序;它们只是返回生成器,除非您遍历它们,否则它们将不会做任何工作。您的整个函数也只产生一个列表,因为它仅包含一个yield
语句,并且它不在循环中,因此只执行一次。
修复这两个问题的方法是使用yield from MergeSort(...)
耗尽您递归创建的生成器。这将耗尽它们,以便它们进行分类工作,并且还导致外部生成器屈服于内部生成器所屈服的任何东西。因此,更改这两行:
yield from MergeSort(lefthalf) yield from MergeSort(righthalf)
示例:
>>> for i in MergeSort([2, 3, 566, 78, 8]): ... print(i) ... [2, 3] [8, 78] [8, 78, 566] [2, 3, 8, 78, 566]
请注意,您没有看到相同长度的列表;递归调用位于较短的列表上,因此它们会产生较短的列表。您也看不到长度为1的列表,因为
yield lst
语句位于if len(lst) > 1:
块内。如果取消缩进该行以使yield lst
为无条件,则可以看到每个调用的结果:
>>> for i in MergeSort([2, 3, 566, 78, 8]):
... print(i)
...
[2]
[3]
[2, 3]
[566]
[78]
[8]
[8, 78]
[8, 78, 566]
[2, 3, 8, 78, 566]