用几个例子看看python的yield作用,顺带整理一下递归问题的求解。
Flatten问题:展开多层嵌套列表
对一个多层嵌套列表,flatten函数应该能按顺序打印出列表中的数字。
版本一:官方实现1
2
3
4
5
6
7def (nested):
try:
for sublist in nested:
for element in flatten2(sublist):
yield element
except TypeError:
yield nested
简洁精巧,但是将在下一个版本中展开递归的说明。
版本二:1
2
3
4
5
6
7
8from collections import Iterable
def flatten1(nested):
if not isinstance(nested, Iterable):
yield nested
else:
for sublist in nested:
for element in flatten1(sublist):
yield element
Target: get a flattened list from nested list
Method: using flatten(nested) to get a generator contains the flattened list of nested
Note: flatten(nested): generator # implies that result is type of generator
We can get recursion:flatten(node) = F( flatten(node.child_1), flatten(node.child_2), …, flatten(node.child_N) )
Then, what is F? We see the recursive case first:
LHS, flatten(node) should make a generator of the flattened node
RHS, node has many child(e.g. child_N). Assume that flatten(any_node) works and then,
we can get many generators(e.g. n-th generator is result of flatten(node.child_N)).
So, F should make a new generator that contains each element in these generators from child node. The core of recursion F can be code as:1
2
3for child_nested in nested: # traverse all child
for element in flatten(child_nested): # traverse element in a child generator
yield element
It is time to talk about base case (terminating case):
When the child_nested is a single element which is not iterable, it refers to the base case(leaf node). Now, for … in … clause will raise an exception because child_nested is not iterable.
flatten(leaf_node) should make a generator of only the single element. so, it can be coded as:1
2
3from collections import Iterable
if not isinstance(nested, Iterable):
yield nested
In this way, we finished coding the recursive function flatten().
My mistakes:omitted else: yield will continue to execute, so else can not be omitted.
base case should return a generator, so the recursive works. A generator makes another generator.
Eight queens puzzle
todo..
Summarypython中的关键字yield某种程度上相当于return(但是会从上次断开的地方继续执行)。
对递归不熟悉,总是陷于细节。
和数学中的函数类似,一个函数由定义域,值域和映射关系组成。通过整体去把握递归函数免于陷入细节。