列表解析
列表解析可以看做是python对于列表生成的一个语法糖,可以使得生成列表的多行代码压缩成一行,如下列表解析所示:
[i for i in range(0,3)]
# 输出:[0,1,2]
换成普通代码为:
l = []
for i in range(0,3):
l.append(i)
l
# 输出:[0,1,2]
这样为阅读代码以及编写带来了方便性
生成器
从形式上看,生成器与列表解析的区别只在于,把"[]"换成"()";我们来看下修改后的代码输出:
(i for i in range(0,3))
# 输出:<generator object <genexpr> at 0x0000016A5A5D8620>
可以看到我们返回的是一个generator对象,而非list。那么这二者有何区别?首先,二者都是可迭代的,但迭代的方式不同:list的内容会整体存储在内从中,在轮循时,依次从内存中取走即可;在轮循generator的元素时(使用next方法),可以"即查即用",也就是轮循到该元素时,即时生成元素,这样节省了内存但延迟了计算负担,可以看做是一种惰性计算。
l = (i for i in range(0,3))
print (next(l))
print (next(l))
print (next(l))
# 输出:0 1 2
yield
上小节我们学习了生成器,那么函数是否可以返回生成器呢?当然可以,但形式不能都是 return (e for e in seq) 这样,理由很简单,如果(e for e in seq)内部有逻辑判断等语法,大量的代码浓缩在一行看起来会很丑陋。通过yield可以解决这个问题。如下代码所示,只要才循环体最后使用 yield 标明你要轮循的元素即可:
def func():
for i in range(0,9):
ret = 0
if i%2 == 0 :
ret = i
else:
continue
yield ret
y = func()
[e for e in y]
# 输出: [0, 2, 4, 6, 8]
注意,使用yield标明需要迭代的对象,就不再需要return语句了。实际上yield本身已经说明了应该return的是什么内容。
参考文献:
[1] Python yield使用浅析