python 中 yield 理解
一、yield 可以用来为一个函数返回值塞数据
# 取出 alist 的每一项,然后把 i + 1 塞进去
def addList(alist):
for i in alist:
yield i + 1
if __name__ == '__main__':
aaa = [1, 3, 2, 9]
print(list(addList(aaa))) # [2, 4, 3, 10]
二、包含 yield 的函数
如果看到某个函数包含了 yield,这意味着这个函数已经是一个 Generator,它的执行会和其他普通的函数有很多不同,yield 是一个表达式
三、应用实例
1、列表数据去重,并保留顺序
def stay(nums):
tmp = set()
for num in nums:
if num not in tmp:
tmp.add(num)
yield num
if __name__ == '__main__':
data = [3, 4, 3, 2, 7, 2, 1, 6, 1]
print(list(set(data))) # [1, 2, 3, 4, 6, 7]
print(list(stay(data))) # [3, 4, 2, 7, 1, 6]
# 这里key指定一个函数,可以比较字典
def stay(nums, key=None):
tmp = set()
for num in nums:
item = num if not key else key(num)
if item not in tmp:
tmp.add(item)
yield num
if __name__ == '__main__':
data = [
{'x': 1, 'y': 2},
{'x': 1, 'y': 3},
{'x': 1, 'y': 2},
{'x': 2, 'y': 4},
]
print(list(stay(data, key=lambda i: (i['x'], i['y']))))
print(list(stay(data, key=lambda i: i['x'])))
2、展开嵌套序列
# 方式一: yield from
from collections import Iterable
def flatten(items, ignore_types=(str, bytes)):
for x in items:
if isinstance(x, Iterable) and not isinstance(x, ignore_types):
yield from flatten(x)
else:
yield x
# 方式二: yield
def flatten(items, ignore_types=(str, bytes)):
for x in items:
if isinstance(x, Iterable) and not isinstance(x, ignore_types):
for i in flatten(x):
yield i
else:
yield x
items = [1, 2, [3, 4, [5, 6], 7], 8]
for item in flatten(items):
print(item)
# 使用python已有方法,以下两种方式只能解决嵌套一层的
# 方法一
data = [[1,2], [4,5], [6,7]]
from functools import reduce
result = reduce(lambda x, y: x+y, data)
print(result)
# 方法二
from itertools import chain
result = list(chain(*data))
print(result)