yield 的理解(2) 顺便 探索下for 循环 ,以及递归

代码目的:

   利用递归,获得一个List中所有的元素

  同时说明一下for ,以及 yield的特点。

代码:

 

net = [[[1,2],3],4,[5,6]]
def flatten(nested = net ,level = 0):
    level +=1
    count = 0 
    try:
        for sublist in nested:
            count += 1
            print ('level {} sublist {} is {} '.format(level,count ,sublist) )
            for element in flatten(sublist,level):
                print('back to level:{}'.format(level))
                yield element 
    except TypeError:
        print('fined node:{}'.format(nested))
        yield nested

  

解释一下代码:

  net

    是要被分解的列表。

  flatten(nested  ,level ) :

    递归调用的函数,用于一层一层的进入嵌套列表,直到找到数据元素

扫描二维码关注公众号,回复: 6818244 查看本文章

    当flatten 的参数nested ,被赋值为数据元素(而不是列表时) ,for sublist in nested 会触发 错误: “TypeError”

    此时进入except TypeError ,Yield nested 会暂停该函数,返回到上一级函数去继续执行。

    注意:Yield并不代表整个程序暂停,而仅是Yield所在函数暂停,并返回值。

    上一个函数此时正在 for element in flatten(sublist,level)  ,于是element = 找到的节点,并借由yield element  ,一层一层往外退。

    当退到shell 层,代码暂停。用户需要继续输入 next(g) ,来调用下一次查找.

    注意,next(g)后,程序是从递归最内层的 yield开始继续执行的。

  第一次执行next(g),以及第二次执行next(g)的入口,流程如下图(为了节约空间,去掉了print()):

    这个图说明了两点:

      1. yield是向上一层返回值,和return的路径一样。

       2. next(g),是从最早的一次yield处回复的。

    可以理解为,当多个yield依次调用时,yield的现场被放入一个“栈”。 使用next恢复时,从栈的最底端保存的yield现场,恢复执行.

    疑问:栈中的其他yield ,是否就丢弃了,暂时没有答案.

实验:

  在python中执行之前的代码:  

net = [[[1,2],3],4,[5,6]]
def flatten(nested = net ,level = 0):
    level +=1
    count = 0 
    try:
        for sublist in nested:
            count += 1
            print ('level {} sublist {} is {} '.format(level,count ,sublist) )
            for element in flatten(sublist,level):
                print('back to level:{}'.format(level))
                yield element 
    except TypeError:
        print('fined node:{}'.format(nested))
        yield nested

  执行过程,和结果如下:

  

>>> g= flatten()
>>> next(g)
level 1 sublist 1 is [[1, 2], 3] 
level 2 sublist 1 is [1, 2] 
level 3 sublist 1 is 1 
fined node:1
back to level:3
back to level:2
back to level:1
1
>>> next(g)
level 3 sublist 2 is 2 
fined node:2
back to level:3
back to level:2
back to level:1
2
>>> next(g)
level 2 sublist 2 is 3 
fined node:3
back to level:2
back to level:1
3
>>> next(g)
level 1 sublist 2 is 4 
fined node:4
back to level:1
4
>>> next(g)
level 1 sublist 3 is [5, 6] 
level 2 sublist 1 is 5 
fined node:5
back to level:2
back to level:1
5
>>> next(g)
level 2 sublist 2 is 6 
fined node:6
back to level:2
back to level:1
6
>>> next(g)
Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    next(g)
StopIteration
>>> 

  可见,列表分层如下:

猜你喜欢

转载自www.cnblogs.com/stonenox/p/11207710.html