个性化阅读
专注于IT技术分析

Python的yield关键字有什么作用?如何理解yield?

Python的yield关键字有什么作用?如何理解yield?在Python中yield关键字的用途是什么?它是做什么的?例如,我试图理解这个代码

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_candidate时会发生什么?是否返回列表?单个元素?它叫什么来着?以后的调用什么时候停止?

要了解yield的作用,你必须了解生成器是什么。在生成器出现之前。

Iterables

创建列表时,你可以逐个阅读其项目。逐个读取它的项称为迭代:

>>> mylist = [1,2,3]

>>> for i in mylist:

…打印(i)

1

2

3

mylist是可迭代的。当你使用列表推导时,你创建一个列表,因此是一个可迭代的:

>>> mylist = [x * x表示范围(3)中的x]

>>> for i in mylist:

…打印(i)

0

1

4

你可以使用“for … in …”的所有内容都是可迭代的;列表,字符串,文件……

这些迭代很方便,因为你可以根据需要阅读它们,但是你将所有值存储在内存中,当你拥有大量值时,这并不总是你想要的。

生成器

生成器是迭代器,是一种只能迭代一次的迭代器。生成器不会将所有值存储在内存中,它们会动态生成值:

>>> mygenerator =(x * x代表范围内的x(3))

>>> for my in mygenerator:

…打印(i)

0

1

4

除了你使用()而不是[]之外,它是一样的。但是,你不能再次在mygenerator中执行i,因为生成器只能使用一次:它们计算0,然后忘记它并计算1,然后逐个计算4。

yield

yield是一个像return一样使用的关键字,除了函数将返回一个生成器。

>>> def createGenerator():

… mylist =范围(3)

…对于我在mylist中:

…产生i * i

>>> mygenerator = createGenerator()#创建一个生成器

>>> print(mygenerator)#mygenerator是一个对象!

<生成器对象createGenerator位于0xb7555c34>

>>> for my in mygenerator:

…打印(i)

0

1

4

这是一个无用的例子,但是当你知道你的函数将返回一组你只需要阅读一次的大量值时它会很方便。

要掌握良率,你必须明白当你调用函数时,你在函数体中编写的代码不会运行。该函数只返回生成器对象,这有点棘手:-)

然后,你的代码将从每次停止的位置继续使用生成器。

现在困难的部分:

第一次调用从函数创建的生成器对象时,它将从头开始运行函数中的代码,直到达到yield,然后它将返回循环的第一个值。然后,每个其他调用将再次运行你在函数中写入的循环,并返回下一个值,直到没有值返回。

一旦函数运行,生成器被认为是空的,但不再生成yield。这可能是因为循环已经结束,或者因为你不再满足“if / else”了。

你的代码解释了

生成器:

#在这里创建将返回生成器的节点对象的方法

def _get_child_candidates(self,distance,min_dist,max_dist):

    #以下是每次使用生成器对象时将调用的代码:

    #如果左侧仍有节点对象的子节点

    #AND如果距离正常,则返回下一个孩子

    如果self._leftchild和距离 –  max_dist <self._median:

        屈服于self._leftchild

    #如果右边还有节点对象的子节点

    #AND如果距离正常,则返回下一个孩子

    如果self._rightchild和距离+ max_dist> = self._median:

        屈服于self._rightchild

    #如果函数到达此处,则生成器将被视为空

    #不超过两个值:左边和右边的孩子

呼叫者:

#创建一个空列表和一个包含当前对象引用的列表

结果,候选人= list(),[self]

#循环候选者(它们在开头只包含一个元素)

候选人:

    #获取最后一个候选者并将其从列表中删除

    node = candidates.pop()

    #获取obj和候选人之间的距离

    distance = node._get_dist(obj)

    #如果距离正常,则可以填写结果

    如果距离<= max_dist且距离> = min_dist:

        result.extend(node._values)

    #在候选人列表中添加候选人的子女

    #所以循环将继续运行,直到它看起来

    #候选人的孩子等所有孩子的孩子

    candidates.extend(node._get_child_candidates(distance,min_dist,max_dist))

返回结果

此代码包含几个智能部分:

循环在列表上迭代,但是循环迭代时列表会扩展:-)这是一种简单的方法来遍历所有这些嵌套数据,即使它有点危险,因为你最终可以得到一个无限循环。在这种情况下,candidate.extend(node._get_child_candidates(distance,min_dist,max_dist))耗尽了生成器的所有值,但同时不断创建新的生成器对象,这些对象将生成与之前的值不同的值,因为它不应用于相同的值节点。

extend()方法是一个列表对象方法,它需要一个iterable并将其值添加到列表中。

通常我们将列表传递给它:

>>> a = [1,2]

>>> b =

赞(0)
未经允许不得转载:srcmini » Python的yield关键字有什么作用?如何理解yield?

评论 抢沙发

评论前必须登录!