Python 代码中的 yield 到底是什么鬼?
嗨,我是虎哥。
今天咱们来聊聊Python里的一个非常重要但也颇具迷惑性的关键词——yield。
作为一个多年的Python程序员,我得说,理解这个关键词的真正用意可是让不少新手朋友抓耳挠腮。
来,让我们一起来拆解一下,看看yield到底是个啥。
迭代与可迭代对象
要搞明白yield,咱们先得弄清楚什么是可迭代对象(iterables)。
所谓可迭代对象,简单来说,就是你可以逐个读取其元素的对象,比如列表、字符串、文件等等。举个例子,当你创建一个列表时,你可以用for循环一个个地读取它的元素:
mylist = [1, 2, 3]for i in mylist:print(i)
mylist = [x*x for x in range(3)]for i in mylist:print(i)
生成器
mygenerator = (x*x for x in range(3))for i in mygenerator:print(i)
yield关键词
def create_generator():mylist = range(3)for i in mylist:yield i*imygenerator = create_generator() # 创建一个生成器print(mygenerator) # mygenerator 是一个生成器对象!
<generator object create_generator at 0xb7555c34>
for i in mygenerator:print(i)
深入理解yield
def _get_child_candidates(self, distance, min_dist, max_dist):if self._leftchild and distance - max_dist < self._median:yield self._leftchildif self._rightchild and distance + max_dist >= self._median:yield self._rightchild
如果节点对象还有左子节点并且距离合适,返回下一个子节点。 如果节点对象还有右子节点并且距离合适,返回下一个子节点。 如果没有更多子节点,生成器会被认为是空的。
result, candidates = list(), [self]while candidates:node = candidates.pop()distance = node._get_dist(obj)if distance <= max_dist and distance >= min_dist:result.extend(node._values)candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))return result
循环遍历一个列表,而列表在循环过程中会扩展。这样可以方便地遍历所有嵌套的数据,虽然有些危险,因为可能会陷入无限循环。在这个例子中,candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))用尽生成器的所有值,但while循环不断创建新的生成器对象,因为它们作用在不同的节点上会产生不同的值。 extend()方法是列表对象的方法,它期望一个可迭代对象,并将其值添加到列表中。通常我们传递一个列表给它,但在代码中,它接收一个生成器,这是个好主意,因为: 你不需要读取值两次。 你可能有很多子节点,不想全部存储在内存中。
高级用法
class Bank():crisis = Falsedef create_atm(self):while not self.crisis:yield "$100"hsbc = Bank()corner_street_atm = hsbc.create_atm()print(next(corner_street_atm)) # 输出 $100print(next(corner_street_atm)) # 输出 $100print([next(corner_street_atm) for _ in range(5)]) # 输出 ['$100', '$100', '$100', '$100', '$100']hsbc.crisis = Trueprint(next(corner_street_atm)) # 输出 StopIteration
itertools模块
import itertoolshorses = [1, 2, 3, 4]races = itertools.permutations(horses)print(list(itertools.permutations(horses)))
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]itertools模块简直是Python程序员的好伙伴,可以让你在处理迭代对象时如虎添翼。
小结
目前,对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
资料包含了《IDEA视频教程》、《最全python面试题库》、《最全项目实战源码及视频》及《毕业设计系统源码》,总量高达650GB。全部免费领取!全面满足各个阶段程序员的学习需求!