何为使用yieldPython 中的关键字?

比如说,我在试着理解这个代码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)编写,他为公制空间制作了一个伟大的Python图书馆。模块 m 空间.

当前回答

简单使用实例 :

>>> def foo():
    yield 100
    yield 20
    yield 3

    
>>> for i in foo(): print(i)

100
20
3
>>> 

如何运行 : 调用时, 函数会立即返回对象。 对象可以传递到下一个( ) 函数 。 当调用下一个( ) 函数时, 您的函数会一直运行到下一个产值, 并为下一个( ) 函数提供返回值 。

在引擎盖下, 循环确认对象是一个生成对象, 并使用下一个( ) 来获取下一个值 。

在一些语言中,比如ES6和更高语言中,它的实施略有不同, 所以下一个是生成对象的成员函数, 每次它得到下一个值时, 你就可以从调用器中传递数值。 所以如果结果是生成器, 那么你可以做类似y=结果。 ext( 555) , 而程序生成值可以说像 z = 产值 999 。 y 的值将是 999 , 下一个产值是 999, 而 z 的值将是 555 , 下一个产值是 555。 Python 获取并发送方法也有类似的效果 。

其他回答

关键要点

  • 缩略Python 语法语法使用yieldKywit 关键字可以使函数返回 a发电机发电机.

  • 发电机是一种振动器,这就是在Python发生环绕的主要方式。

  • 发电机基本上是一种可消耗的功能。return返回一个数值,然后结束一个函数,即yield关键字关键字返回一个值并暂停一个函数。

  • 何时next(g)调用一个发电机,函数在剩余部分恢复执行。

  • 只有当函数遇到明示或默示return它实际上结束了。

书写和理解发电机技术

理解和思考发电机的一个简单的方法就是 写一个常规功能print()代替yield:

def f(n):
    for x in range(n):
        print(x)
        print(x * 10)

注意它的产出:

>>> f(3)
0
0
1
10
2
2

当该函数被理解时,替换yield用于print获得产生相同数值的生成器:

def f(n):
    for x in range(n):
        yield x
        yield x * 10

给 :

>>> list(f(3))
[0, 0, 1, 10, 2, 20]

迭代程序协议

答案“什么产量能做什么”可以是简短和简单的, 但是它是更大的世界的一部分, 所谓的“标准协议”。

在迭代协议的发送方,有两种相关对象。易可动的你可以环绕过去的东西。振动器是跟踪环状状态的对象。

在循环协议的消费者方面,我们呼叫erier()在可循环的物体上获得一个迭代器。然后我们拨打下一个( )用于从迭代器中检索值的迭代器上的迭代器。当不再有数据时, a停止试提出例外:

>>> s = [10, 20, 30]    # The list is the "iterable"
>>> it = iter(s)        # This is the "iterator"
>>> next(it)            # Gets values out of an iterator
10
>>> next(it)
20
>>> next(it)
30
>>> next(it)
Traceback (most recent call last):
 ...
StopIteration

为了让这一切变得更容易, 对于卢布人来说,叫它, 下一个代表我们:

>>> for x in s:
...     print(x)
...   
10
20
30

一个人可以写一本关于这一切的书, 但这些都是关键点。 当我教授 Python 课程时, 我发现这是一个最起码的足够解释 来建立理解 并马上开始使用它。 特别是, 写一个函数的把戏print,测试它,然后转换成yield似乎与所有级别的Python程序员合作良好。

yield允许您更聪明地写字for- 通过将循环部分计入一个便于再利用的单独方法。

假设你需要环绕电子表格的所有非空白行,对每行都做一些事情。

for i, row in df.iterrows(): #from the panda package for reading excel 
  if row = blank: # pseudo code, check if row is non-blank...
    continue
  if past_last_row: # pseudo code, check for end of input data
    break
  #### above is boring stuff, below is what we actually want to do with the data ###
  f(row)

如果你需要打电话g(row)在一个类似的循环中,你可能会发现自己重复for语句加有效行的检查,这是枯燥、复杂和易出错的。我们不想重复(DRY 原则) 。

您想要将检查每个记录的代码与实际处理行的代码区分开来, 比如f(row)g(row) .

您可以做一个函数, 将 f() 作为输入参数, 但使用要简单得多yield在一个方法中做所有关于检查有效行以准备拨打 f () 的无聊内容:

def valid_rows():
  for i, row in df.iterrows(): # iterate over each row of spreadsheet
    if row == blank: # pseudo code, check if row is non-blank...
      continue
    if past_last_row: # pseudo code, check for end of input data
      break
    yield i, row

请注意,方法的每次调用将返回下一行,但如果所有行都读取,且for结束, 方法将return通常。下一次调用将开始新的for循环。

现在您可以在数据上写入迭代, 而不必重复对有效行进行无趣的检查( 现在根据自己的方法来计算) , 例如 :

for i, row in valid_rows():
  f(row)

for i, row in valid_rows():
  g(row)

nr_valid_rows = len(list(valid_rows()))

仅此而已。 请注意, 我还没有使用诸如 迭代器、 生成器、 协议、 共同常规等术语 。 我认为这个简单的例子 适用于我们日常的许多编码 。

python 的输出与返回语句类似,但有些差异除外。如果要从函数返回多个值,返回语句将把所有值都作为列表返回,并将其存储在调用符块的内存中。但如果我们不想使用额外的内存,会怎样?相反,我们需要在需要时从函数中获取该值。这是产出的来源。考虑以下函数:

def fun():
   yield 1
   yield 2
   yield 3

打电话的人是:

def caller():
   print ('First value printing')
   print (fun())
   print ('Second value printing')
   print (fun())
   print ('Third value printing')
   print (fun())

上述代码段(调用函数),如果调用,产出:-

First value printing
1
Second value printing
2
Third value printing
3

从上文可以看出, 产出返回其调用器的值, 但当函数再次调用时, 它不会从第一个语句开始, 而是从产出后右侧的语句开始。 在上述示例中, “ 第一值打印” 打印, 函数被调用。 1 被回传并打印。 然后, 打印“ 第二值打印” , 并再次调用有趣 () 。 它不打印 1 (第一个语句) , 而是返回 2 , 也就是说, 仅从产出 1 之后的语句 。 同样的程序会进一步重复 。

缩略yieldPython 中的关键字用于退出代码而不干扰本地变量状态,当函数再次被称为“执行”时,从我们离开代码的最后一点开始。

以下示例说明yield:

def counter():
    x=2
    while x < 5:
        yield x
        x += 1
        
print("Initial value of x: ", counter()) 

for y in counter():
    print(y)

上述代码产生以下输出:

Initial value of x:  <generator object counter at 0x7f0263020ac0>
2
3
4

- 功能 - 返回。

发电机 -- -- 产量(含有一个或多个产量和零或更多回报率)。

names = ['Sam', 'Sarah', 'Thomas', 'James']


# Using function
def greet(name) :
    return f'Hi, my name is {name}.'
    
for each_name in names:
    print(greet(each_name))

# Output:   
>>>Hi, my name is Sam.
>>>Hi, my name is Sarah.
>>>Hi, my name is Thomas.
>>>Hi, my name is James.


# using generator
def greetings(names) :
    for each_name in names:
        yield f'Hi, my name is {each_name}.'
 
for greet_name in greetings(names):
    print (greet_name)

# Output:    
>>>Hi, my name is Sam.
>>>Hi, my name is Sarah.
>>>Hi, my name is Thomas.
>>>Hi, my name is James.

发电机看起来像一个函数,但行为举止却像一个迭代器。

发件人继续从它所在的位置执行 。 恢复后, 函数在最后产值运行后立即继续执行 。 这允许它的代码在一段时间内生成一系列的值, 代之以它们一次性计算全部值, 然后把它们像列表一样送回去 。

def function():
    yield 1 # return this first
    yield 2 # start continue from here (yield don't execute above code once executed)
    yield 3 # give this at last (yield don't execute above code once executed)

for processed_data in function(): 
    print(processed_data)
    
#Output:

>>>1
>>>2
>>>3

注:放弃不应在尝试中.最终建造。