yield
关键字在Python中的用途是什么?
例如,我试图理解这段代码1:
def _get_child_candidates(self, distance, min_dist, max_dist):
if self._leftchild and distance - max_dist < self._median:
yield self._leftchild
if self._rightchild and distance + max_dist >= self._median:
yield self._rightchild
这是呼叫者:
result, candidates = [], [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
_get_child_candidates
调用该方法会发生什么?是否返回列表?一个元素?再叫一次吗?后续通话什么时候停止?
1.这段代码是由Jochen Schulz(jrschulz)编写的,Jochen Schulz是一个很好的用于度量空间的Python库。这是完整源代码的链接:Module mspace。
(我下面的回答仅从使用Python生成器的角度讲,而不是生成器机制的基础实现,它涉及堆栈和堆操作的一些技巧。)
在python函数中
yield
使用when 代替areturn
时,该函数变成了一个特殊的名称generator function
。该函数将返回一个generator
类型的对象。该yield
关键字是一个标志,通知蟒蛇编译器将特殊对待这样的功能。普通函数将在返回一些值后终止。但是在编译器的帮助下,可以将 generator函数视为可恢复的。也就是说,将恢复执行上下文,并且将从上次运行继续执行。在您显式调用return之前,它将引发StopIteration
异常(这也是迭代器协议的一部分),或到达函数的结尾。我发现了很多关于引用的generator
,但是这一个从中functional programming perspective
是最易消化的。(现在,我想根据我自己的理解来讨论其背后的原理
generator
和iterator
基础。我希望这可以帮助您掌握迭代器和生成器的基本动机。这种概念也出现在其他语言中,例如C#。)据我了解,当我们要处理一堆数据时,通常先将数据存储在某个地方,然后再逐一处理。但是这种幼稚的方法是有问题的。如果数据量巨大,则预先存储它们是很昂贵的。因此
data
,为什么不直接存储自身,为什么不metadata
间接存储某种形式,即the logic how the data is computed
。有两种包装此类元数据的方法。
as a class
。这就是所谓的iterator
实现迭代器协议的人(即__next__()
和__iter__()
方法)。这也是常见的迭代器设计模式。as a function
。这就是所谓的generator function
。但是在后台,返回的generator object
静态IS-A
迭代器仍然存在,因为它也实现了迭代器协议。无论哪种方式,都会创建一个迭代器,即某个可以为您提供所需数据的对象。OO方法可能有点复杂。无论如何,要使用哪一个取决于您。