因为不需要写 lambda 表达式。
可以很容易地跳过原列表中的某些数据。
# 列表推导
l = [i for i in range(5)]
# [0, 1, 2, 3, 4]
print(l)
# 字典推导
d = {i: i ** 2 for i in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
print(d)
推导的时候,可以使用多个 if 条件。如果这些 if 条件出现在同一层循环内,那么它们之间默认是 and 关系,也就是必须同时成立。
在推导时,每一层的 for 子表达式都可以带有 if 条件
在表示推导逻辑时,最多只应该写两个子表达式(例如两个 if 条件、两个 for 循环,或者一个 if 条件与一个 for 循环)否则,应该采用 if 和 for 语句来实现,或编写辅助函数。
编写推导式与生成器表达式时,可以在描述条件的那一部分通过赋值表达式定义变量,并在其他部分复用该变量,可使程序简单易读。
建议赋值表达式只出现在推导逻辑的条件之中。
使用生成器可以降低对内存的消耗。
生成器函数所返回的迭代器是有状态的,无法重复调用。
函数和方法收到的参数如果要迭代许多次,那就要小心,如果这些参数是迭代器的话,就可能得不到预期的值。
Python 的迭代器协议确定了容器与迭代器应该怎样跟内置的 iter 及 next 函数、for 循环及相关的表达式交互:
foo.__iter__
的特殊方法,该方法必须返回迭代器对象(这个迭代器对象本身要实现__next__
特殊方法)要想让自定义的容器类型可以迭代,只需要把__iter__
方法实现为生成器即可。
可以把值传给 iter 函数,检测它返回的是不是那个值本身。如果是,就说明这是个普通的迭代器,而不是一个可以迭代的容器。另外,也可以用内置的 isinstance 函数判断该值是不是 collections.abc.Iterator 类的实例。
要想处理大规模的数据,可以使用生成器表达式(generator expression)来做,它扩展了列表推导式与生成器机制。
生成器表达式可以组合起来,编写一条新的生成器表达式(连锁反应):
l = [1, 2, 3, 4, 5]
it = (i for i in l)
it2 = ((i + 1, i ** 2) for i in it)
print(next(it)) # 1
print(next(it2)) # (3, 4)
print(next(it)) # 3
print(next(it)) # 4
用yeild from
优化for-yeild
结构:
更快,层次结构更分明。
替代方案:通过把迭代器传给函数,通过 next 函数推进该迭代器返回需要用到的参数
优点:
缺点:
解决办法:定义一个有状态的闭包
如果要实现比较难写的迭代逻辑,那么应该先查看 itertools 的文档(在 Python 解释器界面输入 help(itertools)