多层列表嵌套展开(生成器版)yield from实例

如果你有一个这样多层嵌套的列表:
a = [1, 2, 3, [4, [5, 6, 7], 8], 9, 10, [11, 12, 13], 14]
如果你要把它平铺成这样:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
很多人都会使用递归加循环来师兄:

# -*- coding: utf-8 -*-
# @Time    : 2019/7/30 上午 9:41
# @Author  : lh
# @Email   : [email protected]
# @File    : 递归版.py
# @Software: PyCharm

"""
使用递归和循环
"""
# 这是要展开的多层嵌套列表,需要变成[1,2,3,4,,5,6....,12,13]这样的列表
a = [1, 2, 3, [4, [5, 6, 7], 8], 9, 10, [11, 12, 13]]


def spread(deep_list, result_list):
    for i in deep_list:
        if isinstance(i, list):
            spread(i, result_list)
        else:
            result_list.append(i)


good_list = []
spread(a, good_list)
print(good_list)

使用递归和循环虽然可以达到效果,但是需要把储存结果的列表作为参数不断递归的传入:
但是你如果使用生成器的话,就会变得简单很多了

# -*- coding: utf-8 -*-
# @Time    : 2019/7/30 上午 9:54
# @Author  : lh
# @Email   : [email protected]
# @File    : 生成器版.py
# @Software: PyCharm
a = [1, 2, 3, [4, [5, 6, 7], 8], 9, 10, [11, 12, 13], 14]


def spread(deep_list):
    for i in deep_list:
        if isinstance(i, list):
            # yield from是在python3.3之后才引入的
            yield from spread(i)
        else:
            yield i

result = [x for x in spread(a)]
print(result)

如果你对生成器不是很熟悉的话,那就看看下面的例子吧:

# -*- coding: utf-8 -*-
# @Time    : 2019/8/1 下午 11:49
# @Author  : hongliu
# @Email   : @qq.com
# @File    : demo4.py
# @Software: PyCharm

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

调用的话:
在这里插入图片描述
可以看到,odd不是普通函数,而是generator,在执行过程中,遇到yield就中断,下次又继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就报错。

最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
例如:

# -*- coding: utf-8 -*-
# @Time    : 2019/7/30 下午 4:56
# @Author  : lh
# @Email   : [email protected]
# @File    : demo2.py
# @Software: PyCharm

# 字符串
astr = 'ABC'
# 列表
alist = [1, 2, 3]
# 字典
adict = {"name": "wangbm", "age": 18}
# 生成器
agen = (i for i in range(4, 8))


def gen(*args, **kw):
    """
    最难理解的就是generator和函数的执行流程不一样。
    函数是顺序执行,遇到return语句或者最后一行函数语句就返回。
    而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
    :param args:
    :param kw:
    :return:
    """
    for item in args:
        # yield from后面加上可迭代对象,他可以把可迭代对象里的每个元素一个一个的yield出来,对比yield来说代码更加简洁,结构更加清晰。
        yield from item


new_list = gen(astr, alist, adict, agen)
print(new_list)
# for i in new_list:
#     print(i)
print(list(new_list))
# ['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]

发布了59 篇原创文章 · 获赞 18 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_38091140/article/details/98118123